반응형
@ExceptionHandler를 이용한 예외 처리
앞서 배운 @ExceptionHandler를 이용해서 실습 중인 도서 쇼핑몰 구현에서
존재하지 않는 도서 아이디 요청 시 예외 처리를 구현합니다.
BookIdException.java
BookIdException 클래스를 생성하고 다음과 같은 내용을 추가해줍니다.
package com.springmvc.exception;
@SuppressWarnings("serial")
public class BookIdException extends RuntimeException{
private String bookId;
public BookIdException(String bookId) {
this.bookId = bookId;
}
public String getBookId() {
return bookId;
}
}
BookRepositoryImpl.java
getBookById() 메소드를 다음과 같이 수정해줍니다.
package com.springmvc.repository;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.springmvc.domain.Book;
import com.springmvc.exception.BookIdException;
import java.util.ArrayList;
import java.util.HashSet;
import org.springframework.stereotype.Repository;
@Repository
public class BookRepositoryImpl implements BookRepository {
private List<Book> listOfBooks = new ArrayList<Book>();
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() {
return listOfBooks;
}
public List<Book> getBookListByCategory(String category) {
List<Book> booksByCategory = new ArrayList<Book>();
for(int i=0;i<listOfBooks.size();i++) {
Book book = listOfBooks.get(i);
if(category.equalsIgnoreCase(book.getCategory()))
booksByCategory.add(book);
}
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> booksByFilter = filter.keySet();
if(booksByFilter.contains("publisher")) {
for(int j=0;j<filter.get("publisher").size();j++) {
String publisherName = filter.get("publisher").get(j);
for(int i=0;i<listOfBooks.size();i++) {
Book book = listOfBooks.get(i);
if(publisherName.equalsIgnoreCase(book.getPublisher()))
booksByPublisher.add(book);
}
}
}
if(booksByFilter.contains("category")) {
for(int i=0;i<filter.get("category").size();i++) {
String category = filter.get("category").get(i);
List<Book> list = getBookListByCategory(category);
booksByCategory.addAll(list);
}
}
booksByCategory.retainAll(booksByPublisher);
return booksByCategory;
}
public Book getBookById(String bookId) {
Book bookInfo = null;
for (int i=0;i<listOfBooks.size();i++) {
Book book = listOfBooks.get(i);
if(book!=null&&book.getBookId()!=null&&book.getBookId().equals(bookId)) {
bookInfo = book;
break;
}
}
if(bookInfo==null)
throw new BookIdException(bookId);
return bookInfo;
}
public void setNewBook(Book book) {
listOfBooks.add(book);
}
}
검색한 bookId가 없는 경우 예외 클래스인 BookIdException 클래스를 호출합니다.
실행 결과
bookId가 없는 경우 다음과 같은 실행결과가 출력됩니다.
BookController.java
@ExceptionHandler를 설정한 handleError() 메소드를 작성해줍니다.
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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;
@Controller
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
@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(@ModelAttribute("NewBook") Book book) {
MultipartFile bookImage = book.getBookImage();
String saveName = bookImage.getOriginalFilename();
File saveFile = new File("C:\\upload",saveName);
if(bookImage!=null && !bookImage.isEmpty()) {
try {
bookImage.transferTo(saveFile);
} 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.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;
}
}
BookIdException 예외 클래스를 value 속성 값으로 설정합니다.
ModelAndView 클래스의 mav 인스턴스를 생성합니다.
mav의 invalidBookId에 요청한 도서 ID 값을 저장하고
exception에 예외 처리 클래스 BookIdException을 저장하고
url에서 요청 URL과 요청 쿼리문을 저장합니다.
그 후에 errorBook.jsp 파일을 출력합니다.
errorBook.jsp
예외 처리 뷰 페이지를 생성해줍니다.
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<link href="<c:url value="/resources/css/bootstrap.min.css"/>" rel="stylesheet">
<title>예외 처리</title>
</head>
<body>
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="../home">Home</a>
</div>
</div>
</nav>
<div class="jumbotron">
<div class="container">
<h2 class="alert alert-danger">
해당 도서가 존재하지 않습니다.<br>
도서 ID : ${invalidBookId }
</h2>
</div>
</div>
<div class="container">
<p>${url }</p>
<p>${exception }</p>
</div>
<div class="container">
<p>
<a href="<c:url value="/books"/>" class="btn btn-secondary">
도서목록 »</a>
</p>
</div>
</body>
</html>
실행 결과
존재하지 않는 도서 ID를 입력하면 다음과 같은 실행 결과가 나옵니다.
반응형
'SPRING' 카테고리의 다른 글
[SPRING]#37 도서 쇼핑몰 구현 (예외 처리6) (0) | 2024.01.16 |
---|---|
[SPRING]#36 도서 쇼핑몰 구현 (예외 처리5) (0) | 2024.01.16 |
[SPRING]#34 도서 쇼핑몰 구현 (예외 처리3) (0) | 2024.01.15 |
[SPRING]#33 도서 쇼핑몰 구현 (예외 처리2) (0) | 2024.01.15 |
[SPRING]#32 도서 쇼핑몰 구현 (예외 처리1) (0) | 2024.01.15 |