简介
错误处理机制说起来是每个网站架构开发的核心部分,很多时候我们并没有去关注他们,其实错误在我们日常访问过程中时长出现,对错误机制进行了解也是开发一个好的网站所必备的技能之一。
默认错误反馈
spring boot默认会根据不同的请求客户端,返回不同的结果:
- 返回一个默认的错误页面
当我们使用web访问出错的时候,会跳到这样的错误页面,其信息如下所示:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Mon Dec 17 14:50:33 CST 2018
There was an unexpected error (type=Bad Request, status=400).
Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'; nested exception is java.lang.NumberFormatException: For input string: "aaa"
- 返回json信息
当我们用其他的客户端,例如postman模拟请求的时候,返回的信息是json数据,如下所示:
{
"timestamp": "2018-12-17T06:59:00.851+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/somepage"
}
这里要模拟一个
页面不存在的错误
错误,最好先把登录过滤器关掉,否则请求任何不存在的页面都会给你过滤到登录界面,不会出现错误信息。
SpringBoot错误处理过程
我们开发网站过程中,显然不会使用这些默认方式,而是要自己去定制反馈结果的。但我们首先还是先去了解SpringBoot的默认错误处理过程,了解一下原理。
参考自动配置类ErrorMvcAutoConfiguration
。我们看看该自动配置类为容器中添加了如下组件:
- DefaultErrorAttributes
帮我们记录错误相关的信息并将其共享; - BasicErrorController
@Controller
@RequestMapping({
"${server.error.path:${error.path:/error}}"})
public class BasicErrorController extends AbstractErrorController {
@RequestMapping(
produces = {
"text/html"}
)
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = this.getStatus(request);
Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
// 去哪个页面作为错误页面:包含页面的地址和内容
ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
return modelAndView != null ? modelAndView : new ModelAndView("error", model);
}
@RequestMapping
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = this.getStatus(request);
return new ResponseEntity(body, status);
}
}
默认处理/error
请求,
- ErrorPageCustomizer
系统出现错误的时候来到error请求进行处理,类似于error.xml
里配置的错误页面规则。 - DefaultErrorViewResolver
错误处理紫步骤
一旦系统出现4XX或者5XX之类的错误,ErrorPageCustomizer就会生效(定制错误的响应规则),就会来到/error
页面,被BasicErrorController控制器处理。观看上述代码我们可以发现,之所以出现两种错误结果,无非就是对error进行处理的controller会根据不同的请求头Accept: text/html
以及postman模拟请求时的请求头Accept:"*/*"
进行不同的反馈,前者返回错误页面信息,后者返回json数据;
- 错误相应页面
protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
Iterator var5 = this.errorViewResolvers.iterator();
ModelAndView modelAndView;
do {
if (!var5.hasNext()) {
return null;
}
ErrorViewResolver resolver = (ErrorViewResolver)var5.next();
modelAndView = resolver.resolveErrorView(request, status, model