本例介绍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); }
来源:https://www.cnblogs.com/h--d/p/12387815.html