spring|各大一线互联网公司还在用SpringBoot这是为什么?( 四 )


org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration 异常自动配置类中定义的 , 如果开发者没有自己提供一个 ErrorAttributes 的实例的话 , 那么 Spring Boot 将自动提供一个 ErrorAttributes 的实例 , 也就是 DefaultErrorAttributes。
基于此, 开发者自定义 ErrorAttributes 有两种方式 :

  1. 直接实现 ErrorAttributes 接口
  2. 继承 DefaultErrorAttributes(推荐) , 因为 DefaultErrorAttributes 中对异常数据的处理已经完成 , 开发者可以直接使用 。
具体定义如下:
@Componentpublic class MyErrorAttributesextends DefaultErrorAttributes {@Overridepublic Map<String Object> getErrorAttributes(WebRequest webRequest booleanincludeStackTrace) {Map<String Object> map = super.getErrorAttributes(webRequestincludeStackTrace);if ((Integer)map.get(\"status\") == 500) {map.put(\"message\" \"服务器内部错误!\");return map;
定义好的 ErrorAttributes 一定要注册成一个 Bean, 这样 , Spring Boot 就不会使用默认的DefaultErrorAttributes 了 , 运行效果如下图:
自定义异常视图
异常视图默认就是前面所说的静态或者动态页面 , 这个也是可以自定义的 , 首先, 默认的异常视图加载逻辑在 org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController 类的errorHtml 方法中 , 这个方法用来返回异常页面+数据 , 还有另外一个 error 方法 , 这个方法用来返回异常数据(如果是 ajax 请求 , 则该方法会被触发) 。
@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)public ModelAndView errorHtml(HttpServletRequest requestHttpServletResponse response) {HttpStatus status = getStatus(request);Map<String Object> model =Collections.unmodifiableMap(getErrorAttributes(request isIncludeStackTrace(requestMediaType.TEXT_HTML)));response.setStatus(status.value());ModelAndView modelAndView = resolveErrorView(request response statusmodel);return (modelAndView != null) ? modelAndView : new ModelAndView(\"error\"model);
在该方法中, 首先会通过 getErrorAttributes 方法去获取异常数据(实际上会调用到 ErrorAttributes的实例 的 getErrorAttributes 方法) , 然后调用 resolveErrorView 去创建一个 ModelAndView, 如果这里创建失败 , 那么用户将会看到默认的错误提示页面 。
正常情况下 ,  resolveErrorView 方法会来到 DefaultErrorViewResolver 类的 resolveErrorView 方法中:
@Overridepublic ModelAndView resolveErrorView(HttpServletRequest request HttpStatusstatusMap<String Object> model) {ModelAndView modelAndView = resolve(String.valueOf(status.value())model);if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {modelAndView = resolve(SERIES_VIEWS.get(status.series())model);return modelAndView;
在这里 , 首先以异常响应码作为视图名分别去查找动态页面和静态页面 , 如果没有查找到 , 则再以 4xx或者 5xx 作为视图名再去分别查找动态或者静态页面 。
要自定义异常视图解析 , 也很容易, 由于 DefaultErrorViewResolver 是在ErrorMvcAutoConfiguration 类中提供的实例 , 即开发者没有提供相关实例时 , 会使用默认的DefaultErrorViewResolver, 开发者提供了自己的 ErrorViewResolver 实例后 , 默认的配置就会失效 , 因此 , 自定义异常视图 , 只需要提供 一个 ErrorViewResolver 的实例即可: