【SpringBoot】SpringBoot 错误处理机制(九)

旧街凉风 提交于 2020-03-01 03:42:11

  本例介绍SpringBoot错误处理机制

错误处理现象

  新建一个SpringBoot Web项目,在浏览器中随便输入一个错误地址进行访问,如:http://localhost:8081/test/aa,会出现一个错误页面

  浏览器页面错误:

    

  如果用PostMan请求错误地址,得到一个Json错误

  Json错误:

    

错误处理原理

  可以参考ErrorMvcAutoConfiguration,错误处理的自动配置

  一但系统出现4xx或者5xx之类的错误;ErrorPageCustomizer就会生效(定制错误的响应规则);就会来到/error请求;就会被BasicErrorController处理;

  1、DefaultErrorAttributes: 错误请求中有的属性

1 @Override
2 public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
3     Map<String, Object> errorAttributes = new LinkedHashMap<>();
4     errorAttributes.put("timestamp", new Date());
5     addStatus(errorAttributes, webRequest);
6     addErrorDetails(errorAttributes, webRequest, includeStackTrace);
7     addPath(errorAttributes, webRequest);
8     return errorAttributes;
9 }

 

  2、BasicErrorController: 处理默认/error请求

 1 // 产生error界面
 2 @RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
 3 public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
 4     HttpStatus status = getStatus(request);
 5     Map<String, Object> model = Collections
 6             // getErrorAttributes 获取错误内容
 7             .unmodifiableMap(getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
 8     response.setStatus(status.value());
 9 
10     // 去哪个错误界面
11     ModelAndView modelAndView = resolveErrorView(request, response, status, model);
12     return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
13 }
14 
15 // 产生错误json数据
16 @RequestMapping
17 public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
18     Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
19     HttpStatus status = getStatus(request);
20     return new ResponseEntity<>(body, status);
21 }

  3、ErrorPageCustomizer: 系统出现错误以后来到error请求进行处理;(web.xml注册的错误页面规则)

 1 /**
 2  * {@link WebServerFactoryCustomizer} that configures the server's error pages.
 3  */
 4 private static class ErrorPageCustomizer implements ErrorPageRegistrar, Ordered {
 5 
 6     private final ServerProperties properties;
 7 
 8     private final DispatcherServletPath dispatcherServletPath;
 9 
10     protected ErrorPageCustomizer(ServerProperties properties, DispatcherServletPath dispatcherServletPath) {
11         this.properties = properties;
12         this.dispatcherServletPath = dispatcherServletPath;
13     }
14 
15     // 注入错误页面
16     @Override
17     public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
18         ErrorPage errorPage = new ErrorPage(
19                 this.dispatcherServletPath.getRelativePath(this.properties.getError().getPath()));
20         errorPageRegistry.addErrorPages(errorPage);
21     }
22 
23     @Override
24     public int getOrder() {
25         return 0;
26     }
27 
28 }

    // 错误路径配置

1 @Value("${error.path:/error}")
2 private String path = "/error"; 

  4、DefaultErrorViewResolver: 响应页面去哪个页面是由DefaultErrorViewResolver解析得到的;

@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
    ModelAndView modelAndView = resolve(String.valueOf(status.value()), model);
    if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {

        // status.series() 状态码
        modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);
    }
    return modelAndView;
}

private ModelAndView resolve(String viewName, Map<String, Object> model) {

    //默认SpringBoot可以去找到一个页面? error/404
    String errorViewName = "error/" + viewName;
    //模板引擎可以解析这个页面地址就用模板引擎解析
    TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName,
            this.applicationContext);

    if (provider != null) {
        //模板引擎可用的情况下返回到errorViewName指定的视图地址
        return new ModelAndView(errorViewName, model);
    }
    //模板引擎不可用,就在静态资源文件夹下找errorViewName对应的页面 error/404.html
    return resolveResource(errorViewName, model);
}

 

 

 

 

 

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!