HandlerExceptionResolver接口定义
定义: 根据异常类型匹配处理过程来对异常进行处理
接口定义
public interface HandlerExceptionResolver {
ModelAndView resolveException(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);
}
ExceptionHandlerExceptionResolver
继承关系
初始化过程
同样先来看InitializingBean
@Override
public void afterPropertiesSet() {
//初始化@ControllerAdvices
initExceptionHandlerAdviceCache();
//初始化默认ArgumentResolver
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
//初始化默认ReturnValueHandler
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
private void initExceptionHandlerAdviceCache() {
//获取所有@ControllerAdvices注解的类
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
//进行排序
AnnotationAwareOrderComparator.sort(adviceBeans);
for (ControllerAdviceBean adviceBean : adviceBeans) {
ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(adviceBean.getBeanType());
//将带有@Exceptionhanlder注解的方法添加到exceptionHandlerAdviceCache中
if (resolver.hasExceptionMappings()) {
this.exceptionHandlerAdviceCache.put(adviceBean, resolver);
}
//如果该类同时实现ResponseBodyAdvice接口 ,则添加到responseBodyAdvice中
if (ResponseBodyAdvice.class.isAssignableFrom(adviceBean.getBeanType())) {
this.responseBodyAdvice.add(adviceBean);
}
}
}
过程概括:(过程与RequestMappingHandlerAdapter十分相似)
- 初始化@ControllerAdvices注解的类
- 获取所有@ControllerAdvices注解的类
- 将带有@Exceptionhanlder注解的方法添加到exceptionHandlerAdviceCache中
- 如果该类同时实现ResponseBodyAdvice接口 ,则添加到responseBodyAdvice中
- 初始化默认ArgumentResolver
- 初始化默认ReturnValueHandler
DispatcherServlet调用ExceptionHandlerExceptionResolver过程
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
boolean errorView = false;
//如果发生异常
if (exception != null) {
//如果抛出的是一个处理过的异常
if (exception instanceof ModelAndViewDefiningException) {
//直接从异常中获取ModelAndView
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
//处理异常
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
//真正执行异常处理的过程
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
//视图解析过程
...
//如果是异步处理方式,且处于处理中阶段 则直接返回
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
//触发HandlerExecutionChain中的Intercepter.afterCompletion()回调
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,Object handler, Exception ex) throws Exception {
// Check registered HandlerExceptionResolvers...
ModelAndView exMv = null;
//遍历handlerExceptionResolvers处理异常 处理成功就结束
for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
//调用 HandlerExceptionResolver.resolveException()方法处理异常
exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
//异常处理成功
if (exMv != null) {
//异常处理没结果 则返回空
if (exMv.isEmpty()) {
request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
return null;
}
//得到异常处理后视图
if (!exMv.hasView()) {
exMv.setViewName(getDefaultViewName(request));
}
//不知道啥用
WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
return exMv;
}
//异常处理不成功抛出异常
throw ex;
}
ExceptionHandlerExceptionResolver.resolveException()过程
#org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
//判断是否支持该异常类型的处理
if (shouldApplyTo(request, handler)) {
...
ModelAndView result = doResolveException(request, response, handler, ex);
return result;
}
else {
return null;
}
}
#org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver
@Override
protected final ModelAndView doResolveException(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
return doResolveHandlerMethodException(request, response, (HandlerMethod) handler, ex);
}
#org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver
@Override
protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod, Exception exception) {
//1.根据异常类型得到处理过程ServletInvocableHandlerMethod
ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception);
//不支持该类型异常的处理则返回
if (exceptionHandlerMethod == null) {
return null;
}
//提供参数解析的支持
exceptionHandlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
//提供返回值转化的支持
exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
ServletWebRequest webRequest = new ServletWebRequest(request, response);
//处理过程上下文
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
try {
Throwable cause = exception.getCause();
if (cause != null) {
//2. 参数解析,过程调用
exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, cause, handlerMethod);
}else {
exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, handlerMethod);
}
}
catch (Throwable invocationEx) {
//处理过程中如果发生异常,则视为不支持该异常类型的解析,返回null
return null;
}
//TODO 不知道干嘛
if (mavContainer.isRequestHandled()) {
return new ModelAndView();
}
else {
ModelMap model = mavContainer.getModel();
HttpStatus status = mavContainer.getStatus();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, status);
mav.setViewName(mavContainer.getViewName());
if (!mavContainer.isViewReference()) {
mav.setView((View) mavContainer.getView());
}
if (model instanceof RedirectAttributes) {
Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
request = webRequest.getNativeRequest(HttpServletRequest.class);
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
}
return mav;
}
}
过程总结:
-
根据异常类型得到处理过程ServletInvocableHandlerMethod
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(HandlerMethod handlerMethod, Exception exception) { //HandlerMethod所属的类 Class<?> handlerType = (handlerMethod != null ? handlerMethod.getBeanType() : null); if (handlerMethod != null) { //从exceptionHandlerCache获取局部@ExceptionHandler的缓存 ExceptionHandlerMethodResolver resolver = this.exceptionHandlerCache.get(handlerType); if (resolver == null) { //从该类中得到@ExceptionHandler方法 resolver = new ExceptionHandlerMethodResolver(handlerType); //存到exceptionHandlerCache this.exceptionHandlerCache.put(handlerType, resolver); } //使用局部@ExceptionHandler方法处理异常 Method method = resolver.resolveMethod(exception); if (method != null) { return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method); } } //遍历全局@ExceptionHandler处理异常 for (Entry<ControllerAdviceBean, ExceptionHandlerMethodResolver> entry : this.exceptionHandlerAdviceCache.entrySet()) { if (entry.getKey().isApplicableToBeanType(handlerType)) { ExceptionHandlerMethodResolver resolver = entry.getValue(); Method method = resolver.resolveMethod(exception); if (method != null) { return new ServletInvocableHandlerMethod(entry.getKey().resolveBean(), method); } } } return null; }
-
使用ServletInvocableHandlerMethod进行参数解析,过程调用.(这里的过程和HandlerAdapter中一样,只是把ServletInvocableHandlerMethod中的handler方法换成了异常处理的handler方法)
注意:@ExceptionHandler的异常类型不能重复