本文共 5159 字,大约阅读时间需要 17 分钟。
我们看到自动配置类:ErrorMvcAutoConfiguration 错误处理的自动配置类; 这里面注入了几个很重要的 bean;
错误处理步骤:
一旦系统出现了 4xx 或者 5xx 之类的错误,ErrorPageCustomizer 就会生效(定制错误的响应规则)
@Beanpublic ErrorPageCustomizer errorPageCustomizer(DispatcherServletPath dispatcherServletPath) { // 点进这个类 return new ErrorPageCustomizer(this.serverProperties, dispatcherServletPath);}
ErrorPageCustomizer
发现一个方法registerErrorPages 注册错误页面@Overridepublic void registerErrorPages(ErrorPageRegistry errorPageRegistry) { ErrorPage errorPage = new ErrorPage( // 这里有个 getPath() 路径,我们点进去 this.dispatcherServletPath.getRelativePath(this.properties.getError().getPath())); errorPageRegistry.addErrorPages(errorPage);}// getPatpublic String getPath() { return this.path;}// this.path@Value("${error.path:/error}") private String path = "/error";
系统一旦出现错误之后就会来到 /error 请求进行处理;这个请求会被 BasicErrorController 处理:
@Bean@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)public BasicErrorController basicErrorController(ErrorAttributes errorAttributes, ObjectProvidererrorViewResolvers) { //点进这个类 return new BasicErrorController(errorAttributes, this.serverProperties.getError(), errorViewResolvers.orderedStream().collect(Collectors.toList()));}
BasicErrorController
@Controller// 处理默认的 /error 请求@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); Mapmodel = Collections .unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); // 去哪个页面拿错误页面呢?resolveErrorView 方法 ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);}// 返回 json 类型的数据,其他的客户端请求会被这个方法处理@RequestMappingpublic ResponseEntity
我们来看看resolveErrorView 这个方法
protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status, Mapmodel) { // 拿到所有的 errorViewResolvers 错误视图解析器 for (ErrorViewResolver resolver : this.errorViewResolvers) { ModelAndView modelAndView = resolver.resolveErrorView(request, status, model); if (modelAndView != null) { return modelAndView; } } return null;}
我们在之前看到有这样一个bean DefaultErrorViewResolver 默认的错误视图解析器
@Bean@ConditionalOnBean(DispatcherServlet.class)@ConditionalOnMissingBean(ErrorViewResolver.class)DefaultErrorViewResolver conventionErrorViewResolver() { //点进这个类 return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties);}
DefaultErrorViewResolver
public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered { private static final MapSERIES_VIEWS; static { Map views = new EnumMap<>(Series.class); views.put(Series.CLIENT_ERROR, "4xx");// 客户端错误 views.put(Series.SERVER_ERROR, "5xx");// 服务端错误 SERIES_VIEWS = Collections.unmodifiableMap(views); } // .... @Override// HttpStatus 状态码 public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map 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; } // 去 error 路径下解析视图 private ModelAndView resolve(String viewName, Map model) { // 比如 error/404 error/500 String errorViewName = "error/" + viewName; TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext); if (provider != null) { return new ModelAndView(errorViewName, model); } return resolveResource(errorViewName, model); }//.....
所以说:定制错误页面,我们可以建立一个 error 目录,然后放入对应的错误码html文件! 比如:404.html 500.html 4xx.html 5xx.html
这些页面的信息数据在哪里呢?我们找到 DefaultErrorAttributes 这个bean对象;
@Bean@ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)public DefaultErrorAttributes errorAttributes() { return new DefaultErrorAttributes();}
DefaultErrorAttributes里面有很多的 addxx 方法,就是添加不同的信息;
// addStatus // addErrorDetails // addErrorMessage // addStackTrace // addPath// 这里面存了一些错误的信息,我们可以在错误页面直接取出
转载地址:http://qmuki.baihongyu.com/