Spring Boot「16」自定义错误页面

514 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天,点击查看活动详情

Spring Boot 中提供了一个 ErrorController 接口的一个基本实现 BasicErrorController。 当我们访问 /error 或访问其他的 URL 遇到错误时,请求会路由到 BasicErrorController 中处理。 今天我们将来学习下如何通过配置来调整 BasicErrorController 的行为。

01-Whitelabel Error Page

Spring Boot 提供了一个错误页面 /error,当使用 REST 访问时,会得到如下的响应:

{
  "timestamp": "2022-10-26T07:15:16.468+00:00",
  "status": 404,
  "error": "Not Found",
  "path": "/test"
}

当使用浏览器访问,得到如下的页面:

mvc_whitelabel-error-page.png

可以在 application.properties 中增加server.error.whitelabel.enabled=false来关闭这个功能。 关闭后,浏览器访问 /error 得到的是 Web 容器提供的错误界面,例如 Tomcat 提供的:

mvc_error-page-tomcat.png

Whitelabel error page 是通过 BasicErrorController 来提供的,而后者是通过 ErrorMvcAutoConfiguration 自动配置类自动初始化的。 所以,以下两种方式也可以实现上述关闭 whitelabel 的效果:

  • application.properties 中增加spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration
  • @SpringBootApplication(exclude = {ErrorMvcAutoConfiguration.class})

如何显示自定义的 Whitelabel error page?

如果我们使用 Thymeleaf 作为模板引擎,可以在 resources/templates 下新增 error.html,且其内容为:

<!DOCTYPE html>
<html>
<body>
<h1>Something went wrong! </h1>
<h2>Our Engineers are on it</h2>
<a href="/">Go Home</a>
</body>
</html>

当我们运行后,再次访问 /error 可以得到下面自定义的页面:

mvc_custom-error-page-thymeleaf.png

02-自定义 ErrorController

按照上节中介绍的方法,我们可以调整错误页面的格式。 如果需要修改遇到错误时的处理逻辑,我们可以通过继承 BasicErrorController 的方式实现自己的错误处理器。 例如:

@Controller
public class MyDemoErrorController extends BasicErrorController {

    public MyDemoErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties) {
        super(errorAttributes, serverProperties.getError());
    }

    @RequestMapping("/error")
    public String handleError() {
        //do something like logging
        return "error";
    }
}

当我们通过@Controller将自定义错误处理类注册到容器中时,会阻止 ErrorMvcAutoConfiguration 中对默认 BasicErrorController 的初始化。

@Bean
@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)
public BasicErrorController basicErrorController(ErrorAttributes errorAttributes,
        ObjectProvider<ErrorViewResolver> errorViewResolvers) {
    return new BasicErrorController(errorAttributes, this.serverProperties.getError(),
            errorViewResolvers.orderedStream().collect(Collectors.toList()));
   }