- 토이프로젝트의 예외처리를 어떻게 할까 고민하다 검색과 백기선님 웹MVC강의에 예외처리 부분을 복습하였다. (회사소스에 존재하는 ExceptionHandler에는 로그만 남기도록 되어있었다.)
- MVC에서 요청을 처리하다가 에러가 발생하거나 자바에서 지원하는 예외가 발생했을 때 정의한 핸들러로 그 예외를 어떻게 처리할지?, 어떤응답을 만들지를 정의할 수 있다.
@ExceptionHandler
public String RuntimeExceptionHandler(RuntimeException e, Model model){
model.addAttribute("message", "runtime error");
return "error"
}
- 예외처리를 핸들러를 전역 컨트롤러에 선언할 수 있다. (모든 컨트롤러에 적용됨)
@ControllerAdvice("com.edu.controller")
public class CommonExceptionHandler {
...
}
@ControllerAdvice(assignableTypes = {EventController.class, EventApi.class})
public class CommonExceptionHandler {
...
}
@ControllerAdvice("com.edu.controller")
public class CommonExceptionHandler {
...
}
- @RestControllerAdvice 는 @ResponseBody 가 붙은거 라고 생각하면될듯!
- CommonExceptionHandler.java
@ControllerAdvice
public class CommonExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(CommonExceptionHandler.class);
public static final String DEFAULT_ERROR_VIEW = "exception";
@ExceptionHandler(value = RuntimeException.class)
public ModelAndView defaultRuntimeErrorHandler(HttpServletRequest req, RuntimeException e) {
logger.debug("RuntimeException: " + e);
logger.debug("url: " + req.getRequestURL());
ModelAndView mav = new ModelAndView();
mav.addObject("exception", e);
mav.addObject("url", req.getRequestURL());
mav.setViewName(DEFAULT_ERROR_VIEW);
return mav;
}
}
- LectureControllerTest.java
public class LectureControllerTest extends BaseControllerTest {
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders
.standaloneSetup(lectureController)
.setControllerAdvice(new CommonExceptionHandler())
.build();
}
...
@Test
@Description("Exception 발생 테스트")
public void exceptionTest() throws Exception{
String userId = "admin2";
mockMvc.perform(post("/lecture/checkedLecture")
.param("userId", userId)
).andDo(print())
.andExpect(status().is2xxSuccessful())
.andExpect(view().name("exception"))
.andExpect(model().attributeExists("exception"))
;
}
}
- Error : 개발자가 미리 예측하여 처리할 수 없는 경우 (JVM 자원 부족 등의 문제?)
- 관례적으로 Error에 대해서는 Custom Class를 만들지 않는다
- Exception : 개발자가 구현한 로직에서 발생하기 때문에 미리 예측하여 처리할 수 있음
- RuntimeException
- 처리를 강제하지 않음(동작하다 exception 발생)
- 하위 Exception: NullPoint, IllegalArgument, IndexOutOfBound, System)
- Custom UnChecked Exception 을 만들 경우 RuntimeException 클래스를 상속하여 만든다.
- CheckedException
- 반드시 예외처리를 해야함(처리안하면 컴파일 오류)
- RuntimeException을 제외한 모든 클래스
- Custom checked Exception을 만들 경우 Exception 클래스를 상속하여 만든다.
- 예외처리 팁
- 아무것도안하는 에러처리는 피하기 : catch 영역에 아무 동작도 안하면 예외 발생 시 추적하기 힘들어짐. 처리를 못한다면 로그라도 남길 것
- exception.printStackTrace()는 쓰지 말 것 : 에러가 발생한 원인에 대한 Stack Trace를 추적하여 개발자에게 디버깅할 수 있는 힌트를 제공해주지만, 운영 시 성능을 생각한다면 지양해야한다. java reflection을 사용하여 trace를 추적하기 때문에 오버헤드가 발생한다고한다.
- 반복문 내에서 Checked Exception에 대한 처리는 지양할 것 : 반복문 내에서 Checked Exception에 대한 예외처리 구문이 들어가게 되면 성능은 2배 3배 떨어지게 된다.
- @ControllerAdvice 테스트참고
- Exception 참고