美文网首页
SpringMVC-异常处理(二)

SpringMVC-异常处理(二)

作者: 张明学 | 来源:发表于2020-08-03 22:58 被阅读0次

    通过实现HandlerExceptionResolver接口可以实现对处理的除理,但是还是会留掉一些异常如:RequestParam参数没有传导致的MissingServletRequestParameterException,http的方法有误导致的HttpRequestMethodNotSupportedException等等,这些异常不对被自己定义的HandlerExceptionResolver扑捉。

    异常扑捉的关键点:

    在DispatcherServlet.initHandlerExceptionResolvers()对异常处理类进行初始化并且排序

    private void initHandlerExceptionResolvers(ApplicationContext context) {
       this.handlerExceptionResolvers = null;
    
       if (this.detectAllHandlerExceptionResolvers) {
          // 从Spring容器中查找HandlerExceptionResolver的实现类
          Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils
                .beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
          if (!matchingBeans.isEmpty()) {
             this.handlerExceptionResolvers = new ArrayList<>(matchingBeans.values());
             // 根据HandlerExceptionResolvers实现类的order排序,order越小排在越上面
             AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);
          }
       }
       ...
    }
    

    默认的实现有三个类:ExceptionHandlerExceptionResolver、ResponseStatusExceptionResolver、DefaultHandlerExceptionResolver,对应的order分别0、1、2 我们自己实现HandlerExceptionResolver类对异常处理,如类名为GlobalExceptionResolver,如果不指定order,默认排序就排在最后,即:ExceptionHandlerExceptionResolver、ResponseStatusExceptionResolver、DefaultHandlerExceptionResolver、GlobalExceptionResolver。所以MissingServletRequestParameterException、HttpRequestMethodNotSupportedException等异常会被DefaultHandlerExceptionResolver扑捉。

    重写DefaultHandlerExceptionResolver的异常处理方法

    DefaultHandlerExceptionResolver默认实现了一些异常处理如:HttpRequestMethodNotSupportedException、HttpMediaTypeNotSupportedException等,详见:org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver的doResolveException方法,我们可以继承DefaultHandlerExceptionResolver并重写它的方法。

    public class SampleDefaultHandlerExceptionResolver extends DefaultHandlerExceptionResolver {
    
        /**
         * 重写默认的MissingServletRequestParameterException异常的处理方法
         *
         * @return
         * @throws IOException
         */
        @Override
        protected ModelAndView handleMissingServletRequestParameter(MissingServletRequestParameterException ex,
                                                                    HttpServletRequest request,
                                                                    HttpServletResponse response,
                                                                    @Nullable Object handler) throws IOException {
    
            if (handler instanceof HandlerMethod) {
                return buildJsonResponse(request, response, (HandlerMethod) handler, ex);
            }
    
            return super.handleMissingServletRequestParameter(ex, request, response, handler);
        }
    
    
        /**
         * 构建JSON数据
         *
         * @return
         */
        private ModelAndView buildJsonResponse(HttpServletRequest request,
                                               HttpServletResponse response,
                                               HandlerMethod handlerMethod,
                                               Exception ex) {
    
            BaseResponse baseResponse = new BaseResponse().setCode("10").setMessage(ex.getMessage());
            // 使用jackson,也可以换成fastjson
            ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
            modelAndView.addObject("result", baseResponse);
            return modelAndView;
        }
    
    }
    

    被Spring管理并且设置它的order

    <bean id="sampleDefaultHandlerExceptionResolver" class="com.zmx.SampleDefaultHandlerExceptionResolver">
        <property name="order" value="0"/>
    </bean>
    

    也可以让自定义的异常处理类GlobalExceptionResolver继承DefaultHandlerExceptionResolver,重写需要处理的异常,并且设置order属性

    public class GlobalExceptionResolver extends DefaultHandlerExceptionResolver implements HandlerExceptionResolver {
    
        @Override
        public ModelAndView resolveException(HttpServletRequest request,
                                             HttpServletResponse response,
                                             Object o,
                                             Exception e) {
            if (o instanceof HandlerMethod) {
                HandlerMethod handlerMethod = (HandlerMethod) o;
                log.error("异常#Controller={},Method={}", handlerMethod.getBean(), handlerMethod.getMethod().getName(), e);
                // todo 判断属于Ajax的请求还是普通的页面请求
                if (isAsyncRequest(request, handlerMethod)) {
                    // 返回JSON格式数据
                    return buildJsonResponse(request, response, handlerMethod, e);
                } else {
                    // 返回重定向页面
                    return buildViewResponse(request, response, handlerMethod, e);
                }
            }
            return null;
        }
            ....
        
            /**
         * 重写默认的MissingServletRequestParameterException异常的处理方法
         *
         * @return
         * @throws IOException
         */
        @Override
        protected ModelAndView handleMissingServletRequestParameter(MissingServletRequestParameterException ex,
                                                                    HttpServletRequest request,
                                                                    HttpServletResponse response,
                                                                    @Nullable Object handler) throws IOException {
            return this.resolveException(request, response, handler, ex);
        }
    
    }
    
    <bean id="globalExceptionResolver" class="com.zmx.GlobalExceptionResolver">
        <property name="order" value="0"></property>
    </bean>
    

    这样也可以被我们自己的异常处理类扑捉

    相关文章

      网友评论

          本文标题:SpringMVC-异常处理(二)

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