Spring Boot DefaultErrorViewResolver를 확장하여 오류 화면을 동적으로 사용자 지정
하고 싶은 일
Spring Boot + Thymeleaf에서의 화면 개발에서 어떤 오류가 발생했을 때 상태 코드 (4xx, 5xx 등)에 따라 표시하는 오류 화면을 사용자 정의하고 싶습니다.
Spring Boot Version
2.1.3.RELEASE
BasicErrorController
Spring Boot + Thymeleaf에서의 화면 개발은 에러가 발생했을 때의 엔드포인트가 준비되어 있다. 엔드포인트가 되는 컨트롤러 클래스는 이하.
org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.java
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {
@RequestMapping("${server.error.path:${error.path:/error}}")
의 기술에 있는 바와 같이, application.yaml(properties)에 「server.error.path」로 에러 화면의 URL을 기술해 두면 그 URL이 엔드 포인트가 된다. 설정되어 있지 않으면 디폴트로 「/error」가 엔드포인트가 된다(${error.path:/error}의 기술대로).그 때문에, 개발자가 에러용 컨트롤러를 만들지 않아도, 이하와 같은 구성으로 에러 화면 HTML을 배치해 두는 것만으로 에러 화면의 표시가 가능해진다.
※ http://localhost:8080/error -> 5xx.html
※ http://localhost:8080/error/404 -> 4xx.html
오류 화면 동적 사용자 정의
다만 이 경우, 준비되어 있는 에러 HTML은 정적이기 때문에, 예를 들면 「세션으로부터 로그인 정보를 꺼내 에러 화면 헤더, 꼬리말에 표시한다」 「DB로부터 어느 값을 꺼내 XXX 하고 에러 화면 에 표시한다」와 같이, 동적으로 커스터마이즈하고 싶다고 하는 요구도 나온다.
그런 때는 이하의 요령으로 확장해 본다.
BasicErrorController#resolveErrorView(request, response, status, model)에서 부모 클래스인 AbstractErrorController의 resolveErrorView를 호출하고 있으며, 그 안의 resolver.resolveErrorView(request, status, model)에서 ErrorResolver의 resolveErrorView를 호출하고 있다. resolver는 디폴트로 「org.springframework.boot.autoconfigure.web.servlet.errorDefaultErrorViewResolver」가 이용되기 때문에, 이 클래스를 extends한 Resolver(여기서는 CustomeErrorViewResolver라고 명명)를 작성해, resolveErrorView 메소드를 오버라이드(override) 해 거기에 동적 커스터마이즈 된 ModelAndView를 작성하고 return합니다. 이것만으로 동적 커스터마이즈 가능하다.
org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.java
@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, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
ModelAndView modelAndView = resolveErrorView(request, response, status, model);
return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
}
org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController.java
protected ModelAndView resolveErrorView(HttpServletRequest request,
HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
for (ErrorViewResolver resolver : this.errorViewResolvers) {
ModelAndView modelAndView = resolver.resolveErrorView(request, status, model);
if (modelAndView != null) {
return modelAndView;
}
}
return null;
}
다음과 같은 이미지.
CustomeErrorViewResolver.java
@Component
public class CustomeErrorViewResolver extends DefaultErrorViewResolver {
/**
* Create a new {@link DefaultErrorViewResolver} instance.
* @param applicationContext the source application context
* @param resourceProperties resource properties
*/
public CustomeErrorViewResolver(ApplicationContext applicationContext,ResourceProperties resourceProperties) {
super(applicationContext, resourceProperties);
}
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
final ModelAndView mav = super.resolveErrorView(request, status, model);
if (status.is4xxClientError()) {
// 4XX系エラーの時の処理
} else if (status.is5xxServerError()) {
// 5XX系エラーの時の処理
}
return mav;
}
}
이상입니다.
Reference
이 문제에 관하여(Spring Boot DefaultErrorViewResolver를 확장하여 오류 화면을 동적으로 사용자 지정), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/NagaokaKenichi/items/99a7bd3f95df7a36802e텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)