how to Customize error page springboot

created at 07-05-2021 views: 85

introduction

I don’t know if you have noticed it. If the request goes wrong on the current mainstream websites, there will usually be a friendly prompt page, such as Bilibili. Visit a non-existent page and return to the prompt page:

404 error page

Such a page is obviously much friendlier than returning a bunch of error codes or even stack information.

This article will use SpringBoot 2.3.3 + Thymeleaf to demonstrate how to return to the friendly prompt page in the case of an error request.

1. Build the project

As a demo project, we only need the Web and Thymleaf components. The dependencies in the pom are as follows:

 <dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-thymeleaf</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 <exclusions>
 <exclusion>
 <groupId>org.junit.vintage</groupId>
 <artifactId>junit-vintage-engine</artifactId>
 </exclusion>
 </exclusions>
 </dependency>
 </dependencies>

After setting up the project, write a simple HelloWorldController, even if the environment is set up

@Controller
public class HelloWorldController {
 @GetMapping("hello")
 public String hello() {
 return "hello";
 }
}

2. Customize the error page

It is natural to request the defined /hello interface, but what if you request a URL that does not exist at this time? For example /hi, since this interface is not defined, SpringBoot will return a default error page:

error page

Briefly explain the origin of this page:

When SpringBoot starts, there is a configuration class: ErrorMvcAutoConfiguration will configure some error handling, including the default page when the request is wrong.

The relevant code is as follows:

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "server.error.whitelabel", name = "enabled", matchIfMissing = true)
@Conditional(ErrorTemplateMissingCondition.class)
protected static class WhitelabelErrorViewConfiguration {
   private final StaticView defaultErrorView = new StaticView();
 @Bean(name = "error")
   @ConditionalOnMissingBean(name = "error")
   public View defaultErrorView() {
      return this.defaultErrorView;
 }
 // omit irrelevant code
 }
}

As you can see, the property server.error.whitelabel.enabled controls whether this class is automatically assembled, and its default value is true

You can disable him directly in yml:

server:
 error:
 whitelabel:
 enabled: false

At this time, if you visit the undefined /hi interface again, you will receive the default page returned by Tomcat, prompting HTTP Status 404 – Not Found.

This is because we disabled the default error page and did not specify a new error page. Thymleaf doesn't know what page to render. You can also see this prompt from the backend error message:

Caused by: org.thymeleaf.exceptions.
 TemplateInputException: Error resolving template [error], 
template might not exist or might not be accessible by any of the configured Template Resolvers

Thymeleaf did not find the error template, so it reported an error. You can create a new error.html template in the templates directory, request the undefined /hi interface again, and you will get a customized error page:

So far, a simple global error page is done.

However, although this method is simple, its limitations are obvious. Everything is hard-coded, and it cannot execute business logic when something goes wrong.

3. Custom ErrorController

If you want to perform special handling according to the error type when an error occurs, you need to customize an ErrorController to implement it.

Here is how to return different pages according to different error types:

@Controller
public class CustomErrorController implements ErrorController {
​
 @RequestMapping("/error")
 public String handleError(HttpServletRequest request) {
 Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
 if (status != null) {
 Integer statusCode = Integer.valueOf(status.toString());
​
 if (statusCode == HttpStatus.NOT_FOUND.value()) {
 return "my404";
 } else if (statusCode == HttpStatus.UNAUTHORIZED.value()) {
 return "my401";
 } else if (statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
 return "my500";
 }
 // Other error pages can be expanded later here
 }
 return "my404";
 }

You only need to implement the handlerError method to process the corresponding business logic. If necessary, you can also assemble model data in it.

Explain why there is @RequestMapping("/error"), because the default error handling path is /error, which is defined as follows in ErrorProperties.java:

public class ErrorProperties {
​
/**

Path of the error controller.
*/
@Value("${error.path:/error}")
private String path = "/error";
// Omit...
}

We can modify this path as needed, just configure it in yml and keep the setting of yml consistent with the @RequestMapping value of the ErrorController implementation class.

server:
  error:
  # Use the default /error
  path: /error
  whitelabel:
  enabled: false

At this point, a custom error page that can write business code has been written.

4. Summary

This article introduces the implementation of custom error pages in two different ways:

Default error template
Custom ErrorController
The relevant code in the article has been uploaded to the github of the class representative

created at:07-05-2021
edited at: 07-05-2021: