一 .概述
在springboot之中,为我们的默认的错误处理进行了默认的配置,本此我们来看看错误处理的方式.
二 .错误处理的原理
我们首先找到错误的动配置类之中.
@Configuration @ConditionalOnWebApplication @ConditionalOnClass({ Servlet.class, DispatcherServlet.class }) // Load before the main WebMvcAutoConfiguration so that the error View is available @AutoConfigureBefore(WebMvcAutoConfiguration.class) @EnableConfigurationProperties(ResourceProperties.class) public class ErrorMvcAutoConfiguration {
我们发现配置信息应该在ResourceProperties在中.
我们现在看看这个自动配置向容器之中添加了什么组件.
@Bean @ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT) public DefaultErrorAttributes errorAttributes() { return new DefaultErrorAttributes(); }
添加了一个错误属性的组件.
@Bean @ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT) public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) { return new BasicErrorController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers); }
添加了一个基本的错误处理器组件.
@Bean public ErrorPageCustomizer errorPageCustomizer() { return new ErrorPageCustomizer(this.serverProperties); }
添加一个错误页的组件.
@Bean public static PreserveErrorControllerTargetClassPostProcessor preserveErrorControllerTargetClassPostProcessor() { return new PreserveErrorControllerTargetClassPostProcessor(); }
添加了一个PostProcessor组件.
@Configuration static class DefaultErrorViewResolverConfiguration { private final ApplicationContext applicationContext; private final ResourceProperties resourceProperties; DefaultErrorViewResolverConfiguration(ApplicationContext applicationContext, ResourceProperties resourceProperties) { this.applicationContext = applicationContext; this.resourceProperties = resourceProperties; } @Bean @ConditionalOnBean(DispatcherServlet.class) @ConditionalOnMissingBean public DefaultErrorViewResolver conventionErrorViewResolver() { return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties); } }
上面配置了一个错误视图解析器.
当我们的系统之中出现了异常,比如4XX或者5XX的时候,首先会找到一个错误的页面进行处理.
我们可以从下面看到就是去了/error错误的页面.
@Value("${error.path:/error}") private String path = "/error";
然后就是错误处理器进行处理了.
@Controller @RequestMapping("${server.error.path:${error.path:/error}}") public class BasicErrorController extends AbstractErrorController {
我们发现这个错误处理器正好处理的就是/error的请求.
这样就会进行下面的两个处理方式.
@RequestMapping(produces = "text/html") public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes( request, isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView == null ? new ModelAndView("error", model) : modelAndView); } @RequestMapping @ResponseBody public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = getStatus(request); return new ResponseEntity<Map<String, Object>>(body, status); }
其中,一个就是处理页面的错误,另外一个就是处理其他设备的请求错误.
那么,这些错误信息都存放在哪里了呢?
DefaultErrorAttributes这个组件帮助我们存放了错误的信息.
三.自定义错误信息
[1]页面请求
springboot会帮助我们将浏览器的请求转换到4xx.html或者5xx.html页面之中,这个页面需要存在在error文件夹下面.
看下面的实验:
我们在我们的templates的error里面定义两个页面,一个是4xx.html页面,另外一个就是5xx.html页面.
当我们使用浏览器访问的时候,就会根据错误跳转到不同的页面上.[这个需要视图解析器的支持].
通过这种方式,我们就能完成页面请求的显示了.
[2]在上面我们说到,我们将异常信息存放在DefaultErrorAttributes之中.
另外我们可以使用@ControllerAdvice中添加一个HandlerException进行处理,但是这种方式无法区分是页面请求,还是json请求.
我们就需要进行判断.
我们可以根据produces进行判断,或者我们使用请求转发到/error的请求路径上.
[3]如果需要自定义错误的信息,我们就向容器之中添加一个DefaultErrorAttributes就可以了.
四 .自定义的实例
@Component public class ExceptionHandlerConfig implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 在这里我们能够完成异常的解析工作,这是比较重要的. // 重定向到springboot为我们做的一个错误处理器. ModelAndView mv = new ModelAndView("forword:/error"); return mv; } }
我们首先定义一个异常解析器,这个异常解析器的核心就是需要将请求转发到/error之中,这样我们就能使用springboot的默认的错误处理机制.
@Component public class ErrorAttributesEnhance extends DefaultErrorAttributes{ @Override public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) { // 获取父类之中的错误的属性 Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace); //然后我们可以对这个map进行处理,添加或者删除 return errorAttributes; } }
添加一个异常属性处理存储器,我们可以调用父类获取一些错误的信息,然后可以对这个map进行添加和删除属性.