따라서 exceptionHandler를 사용할 때에도 mediaType에 따라 응답 결과를 처리해야한다.
이 때 가장 많이 고민하게 되는 부분이 Spring Security를 사용하는 경우 응답처리였다.
json으로 요청한 경우는 로그인이 필요하다는 exceptionMessage를 내려보내주고 html로 요청한 경우 security에서 처리한 로그인 페이지로 가는 처리를 할 필요가 있다.
이를 위해서는
- 응답요청에 대한 MediaType
- method 에 설정한 @RequestMapping 타입의 produces의 MediaType
- controller 에 설정한 @RequestMapping 의 produces의 MediaType
이 두 가지에 대해 exceptionHandler에서 확인이 가능해야한다.
다음과 같이 확인이 가능하다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@ControllerAdvice | |
public class GlobalExceptionHandler { | |
@Autowired | |
private ContentNegotiatingViewResolver contentNegotiatingViewResolver; | |
@ExceptionHandler | |
@SneakyThrows | |
public ModelAndView handleException(BlueskyException exception, HandlerMethod handlerMethod, NativeWebRequest request) { | |
boolean isJsonResponse = contentNegotiatingViewResolver.getContentNegotiationManager().resolveMediaTypes(request).contains(MediaType.APPLICATION_JSON); | |
if (!isJsonResponse && handlerMethod.getMethodAnnotation(RequestMapping.class) != null) { | |
isJsonResponse = Arrays.asList(handlerMethod.getMethodAnnotation(RequestMapping.class).produces()).contains(MediaType.APPLICATION_JSON_VALUE); | |
} | |
if (!isJsonResponse && handlerMethod.getMethod().getDeclaringClass().getAnnotation(RequestMapping.class) != null) { | |
isJsonResponse = Arrays.asList(handlerMethod.getMethod().getDeclaringClass().getAnnotation(RequestMapping.class).produces()).contains(MediaType.APPLICATION_JSON_VALUE); | |
} | |
if (!isJsonResponse) { | |
throw exception; | |
} | |
return new ModelAndView("리턴페이지"); | |
} | |
} |