[JAVA] Extend Spring Boot DefaultErrorViewResolver to dynamically customize error screens

Thing you want to do

In screen development with Spring Boot + Thymeleaf, I want to customize the error screen to be displayed according to the status code (4xx, 5xx, etc.) when some error occurs.

Spring Boot Version 2.1.3.RELEASE

BasicErrorController For screen development with Spring Boot + Thymeleaf, an endpoint is prepared for when an error occurs. The controller class that becomes the endpoint is as follows.

org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.java


@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {

As described in @RequestMapping ("$ {server.error.path: $ {error.path: / error}} "), in application.yaml (properties), set "server.error.path" to the error screen. If you describe the URL, that URL will be the endpoint. If not set, "/ error" will be the endpoint by default (as described in $ {error.path: / error}). Therefore, even if the developer does not create an error controller, the error screen can be displayed simply by arranging the error screen HTML in the following configuration. d.PNG ※http://localhost:8080/error -> 5xx.html ※http://localhost:8080/error/404 -> 4xx.html

Dynamically customize the error screen

However, in this case, the prepared error HTML is static, so for example, "take out the login information from the session and display it in the error screen header and footer" "take out a certain value from the DB and XXX it to the error screen There are also requests for dynamic customization, such as "display in."

In such a case, try expanding it as follows. In BasicErrorController # resolveErrorView (request, response, status, model), resolveErrorView of parent class AbstractErrorController is called, and resolveErrorView of ErrorResolver is called in resolver.resolveErrorView (request, status, model) in it. Since the resolver uses "org.springframework.boot.autoconfigure.web.servlet.errorDefaultErrorViewResolver" by default, create a Resolver (named CustomeErrorViewResolver here) that extends this class, and override the resolveErrorView method there. Create a dynamically customized ModelAndView and return. This alone enables dynamic customization.

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;
}

The following image.

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()) {
            //Processing at the time of 4XX system error
       } else if (status.is5xxServerError()) {
            //Processing at the time of 5XX system error
        }
        return mav;
   }
}

that's all.

Recommended Posts

Extend Spring Boot DefaultErrorViewResolver to dynamically customize error screens
Customize REST API error response with Spring Boot (Part 2)
Customize REST API error response with Spring Boot (Part 1)
Introduction to Spring Boot ② ~ AOP ~
Introduction to Spring Boot Part 1
Spring Boot + PostgreSQL error resolution method
How to create your own Controller corresponding to / error with Spring Boot
How to use ModelMapper (Spring boot)
Upgrade spring boot from 1.5 series to 2.0 series
I want to control the default error message of Spring Boot
[Introduction to Spring Boot] Form validation check
Changes when migrating from Spring Boot 1.5 to Spring Boot 2.0
Changes when migrating from Spring Boot 2.0 to Spring Boot 2.2
Javaw.exe error when starting Spring Boot (STS)
How to split Spring Boot message file
Add spring boot and gradle to eclipse
[Spring Boot] How to get properties dynamically from a string contained in a URL
When you want to notify an error somewhere when using graphql-spring-boot in Spring Boot
Spring Boot Whitelabel Error Page and JSON Response
How to use MyBatis2 (iBatis) with Spring Boot 1.4 (Spring 4)
How to use built-in h2db with spring boot
How to make Spring Boot Docker Image smaller
The story of raising Spring Boot 1.5 series to 2.1 series
Try to implement login function with Spring Boot
How to add a classpath in Spring Boot
An introduction to Spring Boot + in-memory data grid
How to bind to property file in Spring Boot
Try to automate migration with Spring Boot Flyway
[Java] Article to add validation with Spring Boot 2.3.1.
I wanted to gradle spring boot with multi-project
Apply Twitter Bootstrap 4 to Spring Boot 2 using Webjars
[Spring Boot] How to refer to the property file
[Introduction to Spring Boot] Authentication function with Spring Security
Spring Boot --How to set session timeout time
Customize the display when an error such as 404 Not Found occurs in Spring Boot