持续创作,加速成长!这是我参与「掘金日新计划 · 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"
}
当使用浏览器访问,得到如下的页面:
可以在 application.properties 中增加server.error.whitelabel.enabled=false来关闭这个功能。
关闭后,浏览器访问 /error 得到的是 Web 容器提供的错误界面,例如 Tomcat 提供的:
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 可以得到下面自定义的页面:
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()));
}