일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- mock
- ExceptionHandler
- junit
- HttpHeader
- nextjs
- namedqueries
- hibernate
- RESTful
- docker
- Spring
- Intellij
- content-type
- docker-compose
- jsonview
- test
- Example
- Spring MVC
- Redis
- MySQL
Archives
- Today
- Total
hellokiseok
@ExceptionHandler 사용법 + Content-Type 별 처리 본문
RESTful 서비스에서, 하나의 URI 에서 Content-Type 에 따라 다른 Exception 처리를 하고싶을때 어떻게 해야할까?
Content-Type 이 application/json 일때 exception 정보를 json 데이터로 받아 볼수 없을까?
방법은 간단하다. 아래 소스를 보면 HttpRequestHeader 정보에서 Content-Type 정보를 읽어올수 있다.
그래서 Response Content-Type 에 따라 다른 ModelAndView 를 생성해주면 된다. json 데이터로 넘겨주고 싶을땐 "jsonView" 를 생성하고 html 로 넘겨주고 싶을때는 jsp view 를 생성해주면 된다.
이렇게 하면 동일한 URI 에서 Content-Type 별로 다른 결과를 받아 볼수 있다. Exception 처리를 원하는 Controller 에서 extends 받으면 된다. (모든 Controller에 일괄 적용하는 방법은 아니다.)
Ajax 요청시 반드시 Header 에 {"Content-Type":"application/json"} 추가 해야 한다.
(흔히 쓰는 javascript 라이브 러리에서는 ajax 요청시 자동으로 {X-Requested-With : XMLHttpRequest} 가 해더로 포함되니 참고하시기 바랍니다.)
MyExceptionHandler.java
import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyExceptionHandler { @ExceptionHandler(value = Exception.class) @ResponseStatus (HttpStatus.INTERNAL_SERVER_ERROR) public ModelAndView exceptionHandler( HttpServletRequest request, HttpServletResponse response, Exception exception) { String contentType = request.getHeader("Content-Type"); ModelAndView model=null; String reason= HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase();; int statusCode= HttpStatus.INTERNAL_SERVER_ERROR.value(); // Content-Type 확인, json 만 View를 따로 처리함. if(contentType!=null && MediaType.APPLICATION_JSON_VALUE.equals(contentType)){ model = new ModelAndView("jsonView"); ResponseStatus annotation = exception.getClass().getAnnotation(ResponseStatus.class); if(annotation!=null){ reason = annotation.reason(); statusCode = annotation.value().value(); } } else { //json 이 아닐경우 error page 로 이동 model = new ModelAndView("error.jsp"); } model.addObject("reason",reason); model.addObject("statusCode",statusCode); response.setStatus(statusCode); return model; } }
MyController.java
import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class MyController extends MyExceptionHandler { @RequestMapping(value = "/", method = RequestMethod.GET) public String test(ModelMap model){ throw new MyException(); } }
MyException.java
import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(value = HttpStatus.FORBIDDEN,reason = "Forbidden Error!!!!") public class MyException extends RuntimeException { public MyException() { super("Forbidden Error!!!!"); } }
Controller 에서 발생되는 Exception 을 그냥 throw 하는것은 좋지 않다, 미리 RuntimeException 으로 따로 정의 하자, 그리고 @ResponseStatus Annotation 을 이용해 reason 과 HttpStatus 를 지정한다.
일반적인 서버 오류는 500, "Internal Server Error" 를 주로 사용하지만 Custome 하게 메시지를 구성해도 상관 없다. 하지만 HttpStatus 는 미리 정의 된것을 사용하자. (HttpStatus.java 를 참고하면 정의된 Status 목록을 확인할수 있다.)