11 도서관리 프로젝트 실습
p215 - src/main/java/boot/start/domain/Book
@Getter @Setter @NoArgsConstructor @AllArgsConstructor
public class Book {
// 인덱스 번호
private Long id;
// 도서 이름
private String title;
// 출판사
private String publisher;
// 판매 가격
private double salePrice;
// 대여 비용
private double rentalPrice;
// 대여자
private String renter;
// 등록일자
private LocalDate registrationDate;
// 수정일자
private LocalDate updateDate;
}
p217 - build.gradle
plugins {
id 'java'
id 'war'
id 'org.springframework.boot' version '3.2.8'
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'education'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
implementation 'jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api'
implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
implementation 'jakarta.servlet:jakarta.servlet-api'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
}
tasks.named('test') {
useJUnitPlatform()
}
p218 - src/main/java/boot/start/repository/BookRepository
public class BookRepository {
private final ConcurrentMap<Long, Book> bookMap = new ConcurrentHashMap<>();
private static Long bookIndex = 0L;
// 싱글톤 인스턴스를 위한 static 변수
private static final BookRepository instance = new BookRepository();
// private 생성자: 외부에서 인스턴스 생성 불가
private BookRepository() {}
// 유일한 인스턴스를 반환하는 메서드
public static BookRepository getInstance() {
return instance;
}
// CREATE: Book 객체 저장
public Book save(Book book) {
book.setId(++bookIndex);
bookMap.put(book.getId(), book);
return book;
}
// READ: ID로 책 검색
public Optional<Book> findById(Long id) {
return Optional.ofNullable(bookMap.get(id));
}
// READ: 모든 책 리스트 반환
public List<Book> findAll() {
return new ArrayList<>(bookMap.values());
}
// UPDATE: 기존 책 정보 수정
public Optional<Book> update(Long id, Book updatedBook) {
if (bookMap.containsKey(id)) {
updatedBook.setId(id); // 기존 ID 유지
bookMap.put(id, updatedBook);
return Optional.of(updatedBook);
}
return Optional.empty();
}
// DELETE: ID로 책 삭제
public boolean delete(Long id) {
return bookMap.remove(id) != null;
}
}
p219, 220, 222, 223, 227, 229 - src/main/java/boot/start/servlet/BookServlet
@WebServlet(name = "BookServlet", urlPatterns = {"/books", "/books/create", "/books/update", "/books/delete", "/books/list"})
public class BookServlet extends HttpServlet {
private final BookRepository bookRepository = BookRepository.getInstance();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getServletPath();
switch (action) {
case "/books/create":
showCreateForm(req, resp);
break;
case "/books/update":
showUpdateForm(req, resp);
break;
case "/books/delete":
deleteBook(req, resp);
break;
case "/books/list":
default:
listBooks(req, resp);
break;
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getServletPath();
switch (action) {
case "/books/create":
createBook(req, resp);
break;
case "/books/update":
updateBook(req, resp);
break;
default:
listBooks(req, resp);
break;
}
}
private void showCreateForm(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
RequestDispatcher dispatcher = req.getRequestDispatcher("/jsp/book/book-form.jsp");
dispatcher.forward(req, resp);
}
private void showUpdateForm(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Long id = Long.parseLong(req.getParameter("id"));
Optional<Book> existingBook = bookRepository.findById(id);
if (existingBook.isPresent()) {
req.setAttribute("book", existingBook.get());
RequestDispatcher dispatcher = req.getRequestDispatcher("/jsp/book/book-form.jsp");
dispatcher.forward(req, resp);
} else {
resp.sendRedirect("/books/list");
}
}
private void createBook(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String title = req.getParameter("title");
String publisher = req.getParameter("publisher");
double salePrice = Double.parseDouble(req.getParameter("salePrice"));
double rentalPrice = Double.parseDouble(req.getParameter("rentalPrice"));
String renter = req.getParameter("renter");
Book newBook = new Book();
newBook.setTitle(title);
newBook.setPublisher(publisher);
newBook.setSalePrice(salePrice);
newBook.setRentalPrice(rentalPrice);
newBook.setRenter(renter);
newBook.setRegistrationDate(LocalDate.now());
newBook.setUpdateDate(LocalDate.now());
bookRepository.save(newBook);
resp.sendRedirect("/books/list");
}
private void updateBook(HttpServletRequest req, HttpServletResponse resp) throws IOException {
Long id = Long.parseLong(req.getParameter("id"));
String title = req.getParameter("title");
String publisher = req.getParameter("publisher");
double salePrice = Double.parseDouble(req.getParameter("salePrice"));
double rentalPrice = Double.parseDouble(req.getParameter("rentalPrice"));
String renter = req.getParameter("renter");
Optional<Book> existingBook = bookRepository.findById(id);
if (existingBook.isPresent()) {
Book bookToUpdate = existingBook.get();
bookToUpdate.setTitle(title);
bookToUpdate.setPublisher(publisher);
bookToUpdate.setSalePrice(salePrice);
bookToUpdate.setRentalPrice(rentalPrice);
bookToUpdate.setRenter(renter);
bookToUpdate.setUpdateDate(LocalDate.now());
bookRepository.update(id, bookToUpdate);
resp.sendRedirect("/books/list");
} else {
resp.sendRedirect("/books/list");
}
}
private void deleteBook(HttpServletRequest req, HttpServletResponse resp) throws IOException {
Long id = Long.parseLong(req.getParameter("id"));
bookRepository.delete(id);
resp.sendRedirect("/books/list");
}
private void listBooks(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<Book> bookList = bookRepository.findAll();
req.setAttribute("books", bookList);
RequestDispatcher dispatcher = req.getRequestDispatcher("/jsp/book/book-list.jsp");
dispatcher.forward(req, resp);
}
}
p225 - src/main/webapp/jsp/book/book-form.jsp
<%@ page import="boot.start.domain.Book" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
Book book = (Book) request.getAttribute("book");
String actionUrl = (book == null) ? "/books/create" : "/books/update?id=" + book.getId();
%>
<!DOCTYPE html>
<html>
<head>
<title><%= (book == null) ? "Create Book" : "Update Book" %></title>
</head>
<body>
<h1><%= (book == null) ? "Create Book" : "Update Book" %></h1>
<form action="<%= actionUrl %>" method="post">
<label for="title">Title:</label>
<input type="text" id="title" name="title" value="<%= (book != null) ? book.getTitle() : "" %>"><br>
<label for="publisher">Publisher:</label>
<input type="text" id="publisher" name="publisher" value="<%= (book != null) ? book.getPublisher() : "" %>"><br>
<label for="salePrice">Sale Price:</label>
<input type="text" id="salePrice" name="salePrice" value="<%= (book != null) ? book.getSalePrice() : "" %>"><br>
<label for="rentalPrice">Rental Price:</label>
<input type="text" id="rentalPrice" name="rentalPrice" value="<%= (book != null) ? book.getRentalPrice() : "" %>"><br>
<label for="renter">Renter:</label>
<input type="text" id="renter" name="renter" value="<%= (book != null) ? book.getRenter() : "" %>"><br>
<input type="submit" value="<%= (book == null) ? "Create" : "Update" %>">
</form>
<a href="/books/list">Back to List</a>
</body>
</html>
p228 - src/main/webapp/jsp/book-list.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="boot.start.domain.Book" %>
<%@ page import="java.util.List" %>
<!DOCTYPE html>
<html>
<head>
<title>Book List</title>
</head>
<body>
<h1>Book List</h1>
<table border="1">
<tr>
<th>ID</th>
<th>Title</th>
<th>Publisher</th>
<th>Sale Price</th>
<th>Rental Price</th>
<th>Renter</th>
<th>Actions</th>
</tr>
<%
List<Book> books = (List<Book>) request.getAttribute("books");
for (Book book : books) {
%>
<tr>
<td><%= book.getId() %></td>
<td><%= book.getTitle() %></td>
<td><%= book.getPublisher() %></td>
<td><%= book.getSalePrice() %></td>
<td><%= book.getRentalPrice() %></td>
<td><%= book.getRenter() %></td>
<td>
<a href="/books/update?id=<%= book.getId() %>">Update</a> |
<a href="/books/delete?id=<%= book.getId() %>">Delete</a>
</td>
</tr>
<%
}
%>
</table>
<a href="/books/create">Add New Book</a>
</body>
</html>
Last updated