과거 우리가 BasicErrorController를 사용했을 때(별다른 설정 없어도 자동으로 등록 해주는),
우리가 템플릿에 /error 경로에 에러 페이지를 에러코드.html로 만들어 두면
아무것도 하지 않아도 에러 발생 시(에러를 뿜거나 아니면 response.sendError()를 하던가) 저 에러 페이지 템플릿을 호출하게끔 해 주었다.
그럼 text/html 같은 경우는 이랬고, API는 어떻게 할까?
아무것도 안해도 된다.
먼저, BasicErrorController를 들어가 보자.
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {
@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = getStatus(request);
Map<String, Object> model = Collections
.unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
ModelAndView modelAndView = resolveErrorView(request, response, status, model);
return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
}
@RequestMapping
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
HttpStatus status = getStatus(request);
if (status == HttpStatus.NO_CONTENT) {
return new ResponseEntity<>(status);
}
Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));
return new ResponseEntity<>(body, status);
}
}
이것이 실제 BasicErrorController의 일부분이며, 보면 text/html 뿐만 아니라
ResponseEntity도 등록해놨다.
html같은 경우는 ModelAndView를 반환하여 템플릿을 호출하고, ResponseEntity<>()는 응답 바디에 그대로 넣는다.
실제로, 아까 ErrorPage 설정해 놨던 걸 @Controller를 빼서 스프링에 등록하는 것들에서 제외시켜 주고,
포스트맨으로 Accept를 application/json으로 한 다음에 에러를 뿜는 컨트롤러를 호출해 보면,
이렇게 뜬다.
참고로, 저 @RequestMapping("${server.error.path:${error.path:/error}}")
에러 경로는
application.properties에서
server.error.path로 수정 가능하다.
//@Component
public class WebServerCustomizer implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> {
@Override
public void customize(ConfigurableWebServerFactory factory) {
ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error-page/404");
ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error-page/500");
ErrorPage errorPageEx = new ErrorPage(RuntimeException.class, "/error-page/500");
factory.addErrorPages(errorPage404, errorPage500, errorPageEx);
}
}
이걸 @Component를 주석처리하며 스프링 빈에 등록되는 것들에서 빼 줬는데, 이렇게 따로 등록해 주지 않아야 기본 BasicErrorController가 호출된다.
참고로,
https://qwefdg3.tistory.com/442
여기에서 말 했던 application.properties에 관한 설정도 API도 똑같이 적용된다.
또 마찬가지로, BasicErrorController를 상속받아서 등록하면, 우리가 등록된 걸로 적용된다.
확장할 수 있는거다.
거기서 JSON 오류 메시지를 변경하거나 가능하다.
그런데 @ExceptionHandler라고 더 좋은 방법이 있다고 한다.
API 오류처리는 API마다(예: 상품API, 멤버API) 다르게 처리해야 할 수도 있고, 아니면 우리 회사의 서버를 여러 회사에서 이용한다면 회사마다 API가 다를 수 있다.
그럴 땐 @ExceptionHandler를 사용하면 된다고 한다.
아마 뭔가 예외처리 관련 인터페이스를 상속받고, 저 태그를 붙이고, 특정 함수를 override 할 것 같다. 왠지 좀 어댑터패턴? 이려나?
'스프링 > 4. 스프링 MVC-2' 카테고리의 다른 글
70. HandlerExceptionResolver로 API 예외 처리 (0) | 2023.09.13 |
---|---|
69. API를 위한 예외처리 기능 (0) | 2023.09.13 |
67. API 예외처리 (0) | 2023.09.12 |
66. BasicErrorController가 제공하는 정보들 (0) | 2023.09.10 |
65. 스프링 부트 오류페이지 (0) | 2023.09.10 |