56일차(2)/Spring(18) : 예외 클래스, Exception Controller
- Spring 프로젝트로 돌아와서, 예외 상황시의 control 방법 추가히기
com.sy.spring04.exception 패키지 생성
ExceptionController 클래스 생성
package com.sy.spring04.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
/*
* Spring MVC가 동작중에 특정 type의 예외가 발생하면 해당 예외를 여기서 처리할 수 있다.
*/
@ControllerAdvice
public class ExceptionController {
//spring Framework가 동작하는 중에 NotDeleteException type의
//예외가 발생하면 호출되는 메소드
@ExceptionHandler(NotDeleteException.class)
public ModelAndView notDelete(NotDeleteException nde) {//메소드의 인자로 예외객체가 전달된다.
ModelAndView mView=new ModelAndView();
//exception이라는 키값으로 예외 객체를 담고
mView.addObject("exception", nde);
//view page(/WEB-INF/views/error/info.jsp) 로 forward 이동해서 예외정보 응답하기
mView.setViewName("error/info");
return mView;
}
}
@ControllerAdvice 어노테이션 붙여주기!
NotDeleteException 생성
package com.sy.spring04.exception;
/*
* 예외 클래스를 만드는 방법
*
* 1. RuntimeException 클래스를 상속받아서 만든다.
* 2. String type 을 전달받는 생성자를 정의한 다음 생성자에 전달되는 문자열을
* 부모 생성자에 전달하는 코드를 작성한다.
* - 이 클래스로 생성된 객체는 getMessage() 라는 메소드를 가지고 있는데
* 해당 메소드는 생성자에 전달받았던 예외 메세지를 리턴해준다.
*
* ex)
* NotDeleteException nde=new NotDeleteException("oh! no");
* String msg=nde.getMessage(); // "oh! no"
*
* - 어디에선가 이 예외를 발생시키고 싶으면 throw 예약어를 활용하면 된다.
*
* ex) throw new NotDeleteException("남의 파일 지우기 없기");
*/
public class NotDeleteException extends RuntimeException{
//생성자
public NotDeleteException(String message) {
super(message);
}
}
[ 예외 클래스를 만드는 방법 ]
1. RuntimeException 클래스를 상속받아서 만든다.
2. String type 을 전달받는 생성자를 정의한 다음, 생성자에 전달되는 문자열을 부모 생성자에 전달하는 코드를 작성한다.
- 이 클래스로 생성된 객체는 getMessage() 라는 메소드를 가지고 있는데, 해당 메소드는 생성자에 전달받았던 예외 메세지를 리턴해준다.
ex)
NotDeleteException nde=new NotDeleteException("oh! no");
String msg=nde.getMessage(); // "oh! no"
- 어디에선가 이 예외를 발생시키고 싶으면 throw 예약어를 활용하면 된다.
ex) throw new NotDeleteException("남의 파일 지우기 없기");
- 예외 클래스를 하나 정의해놓고, 예외클래스를 실행하고 싶을 때 throw로 작성해놓으면
개발자가 의도한 custom 예외가 발생하게 된다.
FileService - deleteFile 메소드
@Override
public void deleteFile(int num, HttpServletRequest request) {
//삭제할 파일의 정보를 얻어오기
FileDto dto=dao.getData(num);
//글 작성자와 로그인된 아이디가 일치하는지 확인해서 일치하면 삭제하고, 일치하지 않으면 예외를 발생시키기
String id=(String)request.getSession().getAttribute("id");
if(!dto.getWriter().equals(id)) {
//예외를 발생시키면 해당 예외를 처리하는 곳으로 실행의 흐름이 넘어간다.
throw new NotDeleteException("남의 파일 지우기 없기!");
}
//파일 시스템에서 삭제(upload 폴더에서 해당파일을 삭제)
String saveFileName=dto.getSaveFileName();
String path=request.getServletContext().getRealPath("/resources/upload")
+File.separator+saveFileName;
//경로를 사용해서 파일객체를 생성해서
new File(path).delete();
//DB에서 파일 정보 삭제
dao.delete(num);
}
- 무조건 삭제하는 것이 아니고, 메소드 실행 전 본인 확인을 거친다.
- 글 작성자와 로그인된 아이디가 일치하는지 확인해서 일치하면 삭제하고, 일치하지 않으면 예외를 발생시키기!
- 에러발생시 에러 정보에 대한 응답을 해주어야 한다.
- 이렇게 중간에 exception 처리를 위한 코드를 넣어준다.
- throw 문으로 들어가서 예외가 실행되면 아래 구문은 실행되지 않는다.
실행의 흐름이 넘어간다!!
- 이렇게 작성하면?
- 이렇게 의도적으로 500번 오류를 발생시켜 응답해줄 수 있다.
- 아래 나온 내용은 tomcat에서 응답해준 것인데, 다른방식으로 처리하고 싶으면
개발자가 예외 컨트롤러에서 직접 컨트롤 할 수 있다.
- @ExceptionHandler 사용. NotDeleteException 클래스를 가져온다.
- 메소드의 인자로 예외 객체가 전달된다.
- 에러정보를 출력하려면 error/info 페이지를 만들어야 한다.
info.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/views/error/info.jsp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h1>Oops!</h1>
<p class="alert alert-danger">
<%--
예외 컨트롤러에서
ModelAndView mView=new ModelAndView();
mView.addObject("exception", nde);
exception이라는 키값으로 예외객체를 담았기때문에
예외메시지는
${exception.message} (는 ${exception.getMessage}를 대신한다.)
로 출력할 수 있다.
--%>
<strong>${exception.message}</strong>
<a href="${pageContext.request.contextPath}/">인덱스로 돌아가기</a>
</p>
</div>
</body>
</html>
- ModelAndView로 담아주었기 때문에, EL로 출력할 수 있다.
- 본인이 아닌 삭제 요청에 대해서 예외 컨트롤러가 잘 동작한다.
- 파일간의 연관성을 보면, 위와 같이 예외객체를 담은 메세지를 호출하는 구조인 것을 알 수 있다.
- 생성자로 전달된것이 뷰페이지에서 활용된다.
- Service에서 throw 하면 예외 컨트롤러가 동작한다!
- 그러면 controller가 수행되고, 아래 구문이 실행된다
- notDelete 메소드가 실행되면서 예외객체를 mView에 담아서 응답하면
뷰페이지로 포워드 이동해서 클라이언트에게 응답한다.
- 요청에 실패하면 예외 클래스를 만들어놓고, 실패 상황 발생시 throw하면 된다.
- 예외컨트롤러에 세부적인 내용(처리, 응답)을 적어둔다.
'국비교육(22-23)' 카테고리의 다른 글
57일차(1)/Spring(20) : 게시판 댓글 기능 코드 리뷰 (0) | 2022.12.27 |
---|---|
56일차(3)/Spring(19) : 게시판 댓글 기능 구현 (0) | 2022.12.27 |
56일차(1)/Spring Boot(2) : Bean 생성하는 방법, AOP 활용 실습 (0) | 2022.12.26 |
55일차(4)/Spring Boot(1) : Spring Boot 기초, AOP의 구조 익히기 (0) | 2022.12.26 |
55일차(3)/Spring(17) : 게시판 글 삭제, 글 수정 기능 구현 (0) | 2022.12.25 |