반응형
CRUD 메소드를 사용해서 신규 도서 삽입하기
앞서 배운 JdbcTemplate 클래스의 update() 메소드를 사용해서 실습 진행 중인 도서 쇼핑몰에서
새로운 도서 정보를 저장하는 기능을 구현해 보겠습니다.
BookRepositoryImpl.java
setNewBook() 메소드를 다음과 같이 수정해 줍니다.
package com.springmvc.repository;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.sql.DataSource;
import com.springmvc.domain.Book;
import com.springmvc.exception.BookIdException;
import java.util.ArrayList;
import java.util.HashSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class BookRepositoryImpl implements BookRepository {
private List<Book> listOfBooks = new ArrayList<Book>();
private JdbcTemplate template;
@Autowired
public void setJdbctemplate(DataSource dataSource) {
this.template = new JdbcTemplate(dataSource);
}
public BookRepositoryImpl() {
Book book1 = new Book("ISBN1234","C#교과서",30000);
book1.setAuthor("박용준");
book1.setDescription(
"C#교과서는 생에 첫 프로그래밍 언어로 C#을 시작하는 독자를 대상으로 한다. 특히 응용프로그래머를 위한 C# 입문서로, C#을 사용하여 게임(유니티), 웹, 모바일, IoT 등을 개발할 때 필요한 C# 기초 문법을 익히고 기본기를 탄탄하게 다지는 것이 목적이다."
);
book1.setPublisher("길벗");
book1.setCategory("IT전문서");
book1.setUnitsInStock(1000);
book1.setReleaseDate("2020/01/01");
Book book2 = new Book("ISBN1235", "Node.js교과서",36000);
book2.setAuthor("조현영");
book2.setDescription(
"이 책은 프런트부터 서버, 데이터베이스, 배포까지 아우르는 광범위한 내용을 다룬다. 군더더기 없는 직관적인 설명으로 기본 개념을 확실히 이해하고, 노드와 기능과 생태계를 사용해 보면서 실제로 동작하는 서버를 만들어보자."
);
book2.setPublisher("길벗");
book2.setCategory("IT전문서");
book2.setUnitsInStock(1000);
book2.setReleaseDate("2020/02/02");
Book book3 = new Book("ISBN1236", "어도비 XD CC 2020",25000);
book3.setAuthor("김두한");
book3.setDescription(
"어도비 XD 프로그램을 통해 UI/UX 디자인을 배우고자 하는 예비 디자이너의 눈높이에 맞게 기본적인 도구를 활용한 아이콘 디자인과 웹&앱 페이지 디자인, UI 디자인, 앱 디자인에 애니메이션과 인터랙션을 적용한 프로토타입을 학습합니다."
);
book3.setPublisher("길벗");
book3.setCategory("IT활용서");
book3.setUnitsInStock(1000);
book3.setReleaseDate("2020/03/03");
listOfBooks.add(book1);
listOfBooks.add(book2);
listOfBooks.add(book3);
}
@Override
public List<Book> getAllBookList() {
String SQL = "SELECT * FROM book";
List<Book> listOfBooks = template.query(SQL, new BookRowMapper());
return listOfBooks;
}
public List<Book> getBookListByCategory(String category) {
List<Book> booksByCategory = new ArrayList<Book>();
String SQL = "SELECT * FROM book where b_category LIKE '%"+category+"%'";
booksByCategory = template.query(SQL, new BookRowMapper());
return booksByCategory;
}
public Set<Book> getBookListByFilter(Map<String, List<String>> filter) {
Set<Book> booksByPublisher = new HashSet<Book>();
Set<Book> booksByCategory = new HashSet<Book>();
Set<String> criterias = filter.keySet();
if(criterias.contains("publisher")) {
for(int j=0;j<filter.get("publisher").size();j++) {
String publisherName = filter.get("publisher").get(j);
String SQL = "SELECT * FROM book where b_publisher LIKE '%"+publisherName+"%'";
booksByPublisher.addAll(template.query(SQL, new BookRowMapper()));
}
}
if(criterias.contains("category") ) {
for(int i=0;i<filter.get("category").size();i++) {
String category = filter.get("category").get(i);
String SQL = "SELECT * FROM book where b_category LIKE '%"+category+"%'";
booksByCategory.addAll(template.query(SQL, new BookRowMapper()));
}
}
booksByCategory.retainAll(booksByPublisher);
return booksByCategory;
}
public Book getBookById(String bookId) {
Book bookInfo = null;
String SQL = "SELECT count(*) FROM book where b_bookId=?";
int rowCount = template.queryForObject(SQL, Integer.class, bookId);
if(rowCount != 0) {
SQL = "SELECT * FROM book where b_bookId=?";
bookInfo = template.queryForObject(SQL, new Object[] {bookId}, new BookRowMapper());
}
if(bookInfo==null)
throw new BookIdException(bookId);
return bookInfo;
}
public void setNewBook(Book book) {
String SQL = "INSERT INTO book (b_bookId, b_name, b_unitPrice, b_author, b_description, b_publisher, b_category, b_unitsInStock, b_releaseDate, b_condition, b_fileName)"
+"Values(?,?,?,?,?,?,?,?,?,?,?)";
template.update(SQL, book.getBookId(), book.getName(), book.getUnitPrice(), book.getAuthor(), book.getDescription(), book.getPublisher(), book.getCategory(), book.getUnitsInStock(), book.getReleaseDate(), book.getCondition(), book.getFileName());
}
}
setNewBook() 메소드는 데이터베이스의 book 클래스에 신규 도서를 저장합니다.
BookController.java
submitAddNewBook() 메소드를 다음과 같이 수정해 줍니다.
package com.springmvc.controller;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.MatrixVariable;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import com.springmvc.domain.Book;
import com.springmvc.exception.BookIdException;
import com.springmvc.exception.CategoryException;
import com.springmvc.service.BookService;
import com.springmvc.validator.BookValidator;
import com.springmvc.validator.UnitsInStockValidator;
@Controller
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
@Autowired
private UnitsInStockValidator unitsInStockValidator;
@Autowired
private BookValidator bookValidator;
@RequestMapping
public String requestBookList(Model model) {
List<Book> list = bookService.getAllBookList();
model.addAttribute("bookList", list);
return "books";
}
@RequestMapping("/all")
public ModelAndView requestAllBooks() {
ModelAndView modelAndView = new ModelAndView();
List<Book> list = bookService.getAllBookList();
modelAndView.addObject("bookList", list);
modelAndView.setViewName("books");
return modelAndView;
}
@RequestMapping("/{category}")
public String requestBooksByCategory(@PathVariable("category") String bookCategory, Model model) {
List<Book> booksByCategory = bookService.getBookListByCategory(bookCategory);
if(booksByCategory==null || booksByCategory.isEmpty()) {
throw new CategoryException();
}
model.addAttribute("bookList", booksByCategory);
return "books";
}
@RequestMapping("/filter/{bookFilter}")
public String requestBooksByFilter(
@MatrixVariable(pathVar="bookFilter") Map<String, List<String>> bookFilter, Model model) {
Set<Book> booksByFilter = bookService.getBookListByFilter(bookFilter);
model.addAttribute("bookList", booksByFilter);
return "books";
}
@RequestMapping("/book")
public String requestBookById (
@RequestParam("id") String bookId, Model model) {
Book bookById = bookService.getBookById(bookId);
model.addAttribute("book", bookById);
return "book";
}
@RequestMapping("/add")
public String requestAddBookForm(@ModelAttribute("NewBook") Book book) {
return "addBook";
}
@PostMapping("/add")
public String submitAddNewBook(@Valid @ModelAttribute("NewBook") Book book, BindingResult result) {
if(result.hasErrors())
return "addBook";
MultipartFile bookImage = book.getBookImage();
String saveName = bookImage.getOriginalFilename();
File saveFile = new File("C:\\upload",saveName);
if(bookImage!=null && !bookImage.isEmpty()) {
try {
bookImage.transferTo(saveFile);
book.setFileName(saveName);
} catch(Exception e) {
throw new RuntimeException("도서 이미지 업로드가 실패하였습니다",e);
}
}
bookService.setNewBook(book);
return "redirect:/books";
}
@ModelAttribute
public void addAttribute(Model model) {
model.addAttribute("addTitle", "신규 도서 등록");
}
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setValidator(bookValidator);
binder.setAllowedFields("bookId","name","unitPrice","author","description","publisher","category","unitsInStock","totalPages","releaseDate","condition","bookImage");
}
@ExceptionHandler(value= {BookIdException.class})
public ModelAndView handleError(HttpServletRequest req, BookIdException exception) {
ModelAndView mav = new ModelAndView();
mav.addObject("invalidBookId",exception.getBookId());
mav.addObject("exception",exception);
mav.addObject("url",req.getRequestURL()+"?"+req.getQueryString());
mav.setViewName("errorBook");
return mav;
}
}
submitAddNewBook() 메소드는 폼에서 입력된 신규 도서를 데이터베이스에 저장합니다.
신규 도서 등록 시 이미지는 C://upload 폴더에 업로드됩니다.
addBook.jsp
다음과 같이 일부 내용을 삭제합니다.
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html>
<head>
<link href="<c:url value="/resources/css/bootstrap.min.css"/>" rel="stylesheet">
<title>도서 등록</title>
</head>
<body>
<div class="container">
<div class="float-right" style="padding-right:30px">
<a href="?language=ko">Korean</a> | <a href="?language=en">English</a>
</div>
<br><br>
<form:form modelAttribute="NewBook"
action="./add?${_csrf.parameterName }=${_csrf.token }"
class="form-horizontal"
enctype="multipart/form-data">
<fieldset>
<legend><spring:message code="addBook.form.subtitle.label"/></legend>
<div class="form-group row">
<label class="col-sm-2 control-label">
<spring:message code="addBook.form.bookId.label"/>
</label>
<div class="col-sm-3">
<form:input path="bookId" class="form-control"/>
</div>
<div class="col-sm-6">
<form:errors path="bookId" cssClass="text-danger"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<spring:message code="addBook.form.name.label"/>
</label>
<div class="col-sm-3">
<form:input path="name" class="form-control"/>
</div>
<div class="col-sm-6">
<form:errors path="name" cssClass="text-danger"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<spring:message code="addBook.form.unitPrice.label"/>
</label>
<div class="col-sm-3">
<form:input path="unitPrice" class="form-control"/>
</div>
<div class="col-sm-6">
<form:errors path="unitPrice" cssClass="text-danger"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<spring:message code="addBook.form.author.label"/>
</label>
<div class="col-sm-3">
<form:input path="author" class="form-control"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<spring:message code="addBook.form.description.label"/>
</label>
<div class="col-sm-5">
<form:textarea path="description" cols="50" rows="2" class="form-control"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<spring:message code="addBook.form.publisher.label"/>
</label>
<div class="col-sm-3">
<form:input path="publisher" class="form-control"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<spring:message code="addBook.form.category.label"/>
</label>
<div class="col-sm-3">
<form:input path="category" class="form-control"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<spring:message code="addBook.form.unitsInStock.label"/>
</label>
<div class="col-sm-3">
<form:input path="unitsInStock" class="form-control"/>
</div>
<div class="col-sm-6">
<form:errors path="unitsInStock" cssClass="text-danger"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<spring:message code="addBook.form.releaseDate.label"/>
</label>
<div class="col-sm-3">
<form:input path="releaseDate" class="form-control"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<spring:message code="addBook.form.condition.label"/>
</label>
<div class="col-sm-3">
<form:radiobutton path="condition" value="New"/>New
<form:radiobutton path="condition" value="Old"/>Old
<form:radiobutton path="condition" value="E-Book"/>E-Book
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<spring:message code="addBook.form.bookImage.label"/>
</label>
<div class="col-sm-7">
<form:input path="bookImage" type="file" class="form-control"/>
</div>
</div>
<div class="form-group row">
<div class="col-sm-offset-2 col-sm-10">
<input type="submit" class="btn btn-primary" value="<spring:message code="addBook.form.button.label"/>" />
</div>
</div>
</fieldset>
</form:form>
</div>
</body>
</html>
[logout] 버튼 표시는 다음 타일즈에서 작성할 것이기 때문에 삭제했습니다.
pom.xml
스프링 시큐리티 태그를 사용하는 의존 라이브러리를 등록합니다.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.springmvc</groupId>
<artifactId>controller</artifactId>
<name>BookMarket</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>11</java-version>
<org.springframework-version>5.3.19</org.springframework-version>
<org.aspectj-version>1.9.9.1</org.aspectj-version>
<org.slf4j-version>1.7.36</org.slf4j-version>
<security.version>5.6.3</security.version>
<commons-fileupload-version>1.4</commons-fileupload-version>
<commons-io-version>2.11.0</commons-io-version>
<org.apache.tiles-version>3.0.8</org.apache.tiles-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${security.version}</version>
</dependency>
<!-- File Upload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons-fileupload-version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Validation -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.2.Final</version>
</dependency>
<!-- Web Flow -->
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-webflow</artifactId>
<version>2.5.1.RELEASE</version>
</dependency>
<!-- Tiles -->
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-servlet</artifactId>
<version>${org.apache.tiles-version}</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-jsp</artifactId>
<version>${org.apache.tiles-version}</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-extras</artifactId>
<version>${org.apache.tiles-version}</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.24</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
스프링 시큐리티 태그를 사용할 수 있습니다.
menu.jsp
메뉴바 템플릿을 다음과 같이 수정합니다.
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="${pageContext.request.contextPath }/home">Book Market</a>
</div>
<div>
<ul class="navbar-nav mr-auto">
<li class="nav-item"><a class="nav-link" href="<c:url value="/home"/>">Home</a></li>
<li class="nav-item"><a class="nav-link" href="<c:url value="/books"/>">Books</a></li>
<li class="nav-item"><a class="nav-link" href="<c:url value="/books/add"/>">Add Book</a></li>
<li class="nav-item"><a class="nav-link" href="<c:url value="/cart/"/>">Cart</a></li>
<li class="nav-item">
<sec:authorize access="isAuthenticated()">
<form:form action="${pageContext.request.contextPath }/logout" method="POST">
<input type="submit" class="btn btn-success" value="Logout"/>
</form:form>
</sec:authorize>
</li>
<li class="nav-item">
<sec:authorize access="!isAuthenticated()">
<a class="nav-link" href="<c:url value="/login"/>">Login</a>
</sec:authorize>
</li>
</ul>
</div>
</div>
</nav>
시큐리티 태그를 사용하기 위해 태그 라이브러리를 선언합니다.
<sec:authorize> 태그를 사용해서 관리자가 인증되면 Logout 버튼을 표시하고
관리자가 미인증되면 Login 버튼을 표시합니다.
실행 결과
/home을 입력 후 Add Book 메뉴를 눌러서 실행하고 새로운 도서를 등록해 봅니다.
다음와 같이 새로운 도서가 등록된 것을 확인하였습니다.
반응형
'SPRING' 카테고리의 다른 글
[SPRING]#85 도서 쇼핑몰 구현 (DB 연동10) (0) | 2024.03.04 |
---|---|
[SPRING]#84 도서 쇼핑몰 구현 (DB 연동9) (0) | 2024.03.04 |
[SPRING]#82 도서 쇼핑몰 구현 (DB 연동7) (0) | 2024.03.03 |
[SPRING]#81 도서 쇼핑몰 구현 (DB 연동6) (0) | 2024.03.03 |
[SPRING]#80 도서 쇼핑몰 구현 (DB 연동5) (0) | 2024.03.03 |