美文网首页
springmvc揭秘异常处理机制

springmvc揭秘异常处理机制

作者: 墨线宝 | 来源:发表于2024-05-27 10:03 被阅读0次

    HandlerExceptionResolver异常处理

    HandlerExceptionResolver是专门进行异常处理的,在render之前进行工作,从异常中解析出ModelAndView

    public interface HandlerExceptionResolver {
      
       ModelAndView resolveException(
             HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);
    
    }
    
    • DefaultHandlerExceptionResolver 根据不同类型的异常来进行解析,response.sendError设置不同的错误码

      response.sendError(HttpServletResponse.SC_NOT_FOUND);
      
    • ExceptionHandlerExceptionResolver 使用@ExceptionHandler注解的方法来进行异常解析

    • ResponseStatusExceptionResolver 解析有@ResponseStatus注解的异常

    • SimpleMappingExceptionResolver 通过配置的异常类和View的映射关系来解析异常

    ExceptionHandlerExceptionResolver

    我一般都是使用@ExceptionHandler注解,所以就以ExceptionHandlerExceptionResolver为例

    所有的HandlerExceptionResolver实现类都是去重写resolveException方法

    // org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver#resolveException
    @Override
    public ModelAndView resolveException(
          HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
            // 判断当前HandlerExceptionResolver是否可以解析
       if (shouldApplyTo(request, handler)) {
         // 判断是否禁用缓存,如果禁用缓存的话,设置响应头
          prepareResponse(ex, response);
         // 具体的处理逻辑
          ModelAndView result = doResolveException(request, response, handler, ex);
          if (result != null) {
             
             // Explicitly configured warn logger in logException method.
             logException(ex, request);
          }
          return result;
       }
       else {
          return null;
       }
    }
    

    shouldApplyTo

    // org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver#shouldApplyTo
    @Override
    protected boolean shouldApplyTo(HttpServletRequest request, Object handler) {
       if (handler == null) {
          return super.shouldApplyTo(request, handler);
       }
       else if (handler instanceof HandlerMethod) {
          HandlerMethod handlerMethod = (HandlerMethod) handler;
          handler = handlerMethod.getBean();
          return super.shouldApplyTo(request, handler);
       }
       else {
          return false;
       }
    }
    
    // org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver#shouldApplyTo
    protected boolean shouldApplyTo(HttpServletRequest request, Object handler) {
            if (handler != null) {
          // mappedHandlers是处理器的集合
          if (this.mappedHandlers != null && this.mappedHandlers.contains(handler)) {
                    return true;
                }
          // mappedHandlerClasses是处理器类型的集合
                if (this.mappedHandlerClasses != null) {
                    for (Class<?> handlerClass : this.mappedHandlerClasses) {
                        if (handlerClass.isInstance(handler)) {
                            return true;
                        }
                    }
                }
            }
            // Else only apply if there are no explicit handler mappings.
            return (this.mappedHandlers == null && this.mappedHandlerClasses == null);
        }
    

    doResolveException

    该方法是处理异常的实际方法

    protected final ModelAndView doResolveException(
          HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    
       return doResolveHandlerMethodException(request, response, (HandlerMethod) handler, ex);
    }
    
    protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request,
                HttpServletResponse response, HandlerMethod handlerMethod, Exception exception) {
            // 找到处理异常的方法
            ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception);
            if (exceptionHandlerMethod == null) {
                return null;
            }
            // 设置argumentResolvers和returnValueHandlers
            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) {
                    // Expose cause as provided argument as well
            // 执行exceptionHandler方法解析异常
                    exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, cause, handlerMethod);
                }
                else {
                    // Otherwise, just the given exception as-is
                    exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, handlerMethod);
                }
            }
            catch (Throwable invocationEx) {
                
                // Continue with default processing of the original exception...
                return null;
            }
    
            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();
                    RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
                }
                return mav;
            }
        }
    

    https://zhhll.icu/2021/框架/springmvc/底层剖析/5.HandlerExceptionResolver/

    本文由mdnice多平台发布

    相关文章

      网友评论

          本文标题:springmvc揭秘异常处理机制

          本文链接:https://www.haomeiwen.com/subject/nbpcqjtx.html