1.异常解析器概览
在 SpringMVC 的异常体系中,处于最顶层的大 Boss 是 HandlerExceptionResolver,这是一个接口,里边只有一个方法:
- public interface HandlerExceptionResolver {
- @Nullable
- ModelAndView resolveException(
- HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);
- }
resolveException 方法就用来解析请求处理过程中所产生的异常,并最终返回一个 ModelAndView。
我们来看下 HandlerExceptionResolver 的实现类:
直接实现 HandlerExceptionResolver 接口的类有三个:
- HandlerExceptionResolverComposite:这个一看又是一个组合,在最近的源码分析中我们已经多次见到 xxxComposite 了,这里就不再赘述。
- DefaultErrorAttributes:这个用来保存异常属性。
-
AbstractHandlerExceptionResolver:这个的子类比较多:
- SimpleMappingExceptionResolver:通过提前配置好的异常类和 View 之间的对应关系来解析异常。
- AbstractHandlerMethodExceptionResolver:处理使用 @ExceptionHandler 注解自定义的异常类型。
- DefaultHandlerExceptionResolver:按照不同类型来处理异常。
- ResponseStatusExceptionResolver:处理含有 @ResponseStatus 注解的异常。
在 SpringMVC 中,大致的异常解析器就是这些,接下来我们来逐个学习这些异常解析器。
2.AbstractHandlerExceptionResolver
AbstractHandlerExceptionResolver 是真正干活的异常解析器的父类,我们就先从他的 resolveException 方法开始看起。
- @Override
- @Nullable
- public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {
- if (shouldApplyTo(request, handler)) {
- prepareResponse(ex, response);
- ModelAndView result = doResolveException(request, response, handler, ex);
- if (result != null) {
- logException(ex, request);
- }
- return result;
- }
- else {
- return null;
- }
- }
- 首先调用 shouldApplyTo 方法判断当前解析器是否可以处理传入的处理器所抛出的异常,如果不支持,则直接返回 null,这个异常将交给下一个 HandlerExceptionResolver 去处理。
- 调用 prepareResponse 方法处理 response。
- 调用 doResolveException 方法实际处理异常,这是一个模版方法,具体的实现在子类中。
- 调用 logException 方法记录异常日志信息。
记录异常日志没啥好说的,doResolveException 则是一个空的模版方法,所以这里对我们来说主要就是两个方法:shouldApplyTo 和 prepareResponse,我们分别来看。
shouldApplyTo
- protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object handler) {
- if (handler != null) {
- if (this.mappedHandlers != null && this.mappedHandlers.contains(handler)) {
- return true;
- }
- if (this.mappedHandlerClasses != null) {
- for (Class<?> handlerClass : this.mappedHandlerClasses) {
- if (handlerClass.isInstance(handler)) {
- return true;
- }
- }
- }
- }
- return !hasHandlerMappings();
- }
这里涉及到了两个对象:mappedHandlers 和 mappedHandlerClasses:
- mappedHandlers:存储的是处理器对象(Controller 或者 Controller 中的方法)
- mappedHandlerClasses:存储的是处理器的 Class。
我们在配置异常解析器的时候可以配置这两个对象,进而实现该异常处理器只为某一个处理器服务,但是一般来说没这种需求,所以大家仅做了解即可。
如果开发者一开始配置了 mappedHandlers 或者 mappedHandlerClasses,则用这两个和处理器去比较,否则就直接返回 true,表示支持该异常处理。
prepareResponse
prepareResponse 方法比较简单,主要是处理一下响应头的缓存字段。
- protected void prepareResponse(Exception ex, HttpServletResponse response) {
- if (this.preventResponseCaching) {
- preventCaching(response);
- }
- }
- protected void preventCaching(HttpServletResponse response) {
- response.addHeader(HEADER_CACHE_CONTROL, "no-store");
- }
这是 AbstractHandlerExceptionResolver 的大致内容,可以看到还是非常 easy 的,接下来我们来看它的实现类。