SpringBoot学习-part27错误处理原理&定制错误页面、数据

    技术2024-08-01  80

    Postman 初步测试,错误页面

    ErrorMvcAutoConfiguration

    1.DefaultErrorAtrributes:

    帮助我们在页面共享信息。

    2.BasicErrorController:

    //默认处理 /error 请求 @Controller @RequestMapping("${server.error.path:${error.path:/error}}") public class BasicErrorController extends AbstractErrorController {...}

    两种请求的处理

    //产生html类型的数据,浏览器产生的错误来到这里处理 @RequestMapping(produces = MediaType.TEXT_HTML_VALUE) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections .unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); //去哪个页面作为错误页面? ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView != null) ? modelAndView : new ModelAndView("error", model); } //产生json类型的数据,其它客户端的错误来到这里进行处理 @RequestMapping public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { HttpStatus status = getStatus(request); if (status == HttpStatus.NO_CONTENT) { return new ResponseEntity<>(status); } Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL)); return new ResponseEntity<>(body, status); }

    resolveErrorView

    protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status, Map<String, Object> model) { for (ErrorViewResolver resolver : this.errorViewResolvers) { ModelAndView modelAndView = resolver.resolveErrorView(request, status, model); if (modelAndView != null) { return modelAndView; } } return null; }

    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())) { modelAndView = resolve(SERIES_VIEWS.get(status.series()), model); } return modelAndView; } private ModelAndView resolve(String viewName, Map<String, Object> model) { //默认去找一个error/错误码的页面,类似 error/404 String errorViewName = "error/" + viewName; //如果模板引擎可以解析这个页面地址,就使用引擎解析 TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext); //如果引擎可用的情况下,就创建并返回一个新的视图 if (provider != null) { return new ModelAndView(errorViewName, model); } //如果无法被引擎解析则去resourceProperties寻找静态资源 return resolveResource(errorViewName, model); } private ModelAndView resolveResource(String viewName, Map<String, Object> model) { //在静态资源文件找errorViewName对应的页面, 比如 error/404.html for (String location : this.resourceProperties.getStaticLocations()) { try { Resource resource = this.applicationContext.getResource(location); resource = resource.createRelative(viewName + ".html"); if (resource.exists()) { return new ModelAndView(new HtmlResourceView(resource), model); } } catch (Exception ex) { } } return null; }

    3.ErrorPageCustomizer:

    @Value("${error.path:/error}") private String path = "/error"; 一旦系统出现4xx或者5xx之类的错误,ErrorPageCustomizer就会生效(定制错误的响应规则) 来到/error请求,

    4.DefaultErrorViewResolver:

    添加第一个自定义的错误页面

    在有模板引擎的情况下: error/状态码.html 放到 templates 文件夹下 也可以使用4xx和5xx作为错误页面的文件名放在error文件夹下

    通过DefaultErrorAttributes的源码可以知道,错误页面能够获得信息:

    timestamp: 时间戳 status: 状态码 error: 错误提示 exception: 异常对象 message: 异常信息 errors: jsr303数据校验相关错误

    如果模板引擎找不到对应的资源,比如将错误页面放到静态资源文件件下

    此时,无法动态获得错误信息

    模板引擎的templates文件夹和 静态资源 文件夹下都没有

    此时,来到SpringBoot的默认错误提示页面

    Processed: 0.018, SQL: 9