自定义SimpleMappingExceptionResolver实现个性化的异常处理

Spring MVC 的SimpleMappingExceptionResolver是一个简单的异常处理bean,说他简单是因为SimpleMappingExceptionResolver只能获得内置的异常信息,用户无法将自定义的异常信息带到页面上供用户查看,且SimpleMappingExceptionResolver不支持ajax的异常处理。为了能够让异常体制更具个性化。我们常做的方法是实现HandlerExceptionResolver接口自定义自己的异常处理器。下面介绍另外一种方法:重写SimpleMappingExceptionResolver来实现异常的个性化。

SimpleMappingExceptionResolver异常处理其核心是doResolveException()

protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) {
   String viewName =  this.determineViewName(ex, request);
    if(viewName !=  null) {
       Integer statusCode =  this.determineStatusCode(request, viewName);
        if(statusCode !=  null) {
            this.applyStatusCodeIfPossible(request, response, statusCode.intValue());
       }

        return  this.getModelAndView(viewName, ex, request);
   }  else {
        return  null;
   }
}
所以我们要做的就是重写这个方法

package com.me.common.exception;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.io.IOException;
import java.util.Properties;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.me.endpoint.GrantResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
public  class MyExceptionResolver  extends SimpleMappingExceptionResolver {


    private String defaultErrorView;

    private Properties exceptionMappings;

    public MyExceptionResolver() {
   }

   @Override
    public  void setDefaultErrorView(String defaultErrorView) {
        this.defaultErrorView = defaultErrorView;
        super.setDefaultErrorView(defaultErrorView);
   }

   @Override
    public  void setExceptionMappings(Properties exceptionMappings) {
        this.exceptionMappings = exceptionMappings;
        super.setExceptionMappings(exceptionMappings);
   }

   @Override
    protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) {
        boolean isAjax =  this.isJsonRequest(handler);
        return isAjax? this.jsonExceptionHandler(response, ex): this.generalExceptionHandler(request, response, ex);
   }

    private  boolean isJsonRequest(Object handler) {
       HandlerMethod method = (HandlerMethod)handler;
       ResponseBody body = (ResponseBody)method.getMethodAnnotation(ResponseBody.class);
        return body !=  null;
   }
   
      //ajax异步请求
    private ModelAndView jsonExceptionHandler(HttpServletResponse response, Exception e) {

       ServletOutputStream stream =  null;

        try {
           response.setContentType("application/json");
           response.setCharacterEncoding("UTF-8");
           response.setHeader("Cache-Control", "no-cache, must-revalidate");
           stream = response.getOutputStream();
           String errorMsg  =  "系统出错了";
            if(e  instanceof   GenericException  || e  instanceof  EcouponException){
               errorMsg  =  e.getMessage();
           }
           stream.write(JSON.toJSONBytes( new GrantResult("faild", errorMsg),  new SerializerFeature[]{SerializerFeature.QuoteFieldNames}));
       }  catch (Exception var16) {

       }  finally {
            if(stream !=  null) {
                try {
                   stream.close();
               }  catch (IOException var15) {
                   var15.printStackTrace();
               }
           }
       }
        return  new ModelAndView();
   }

      //普通请求
    private ModelAndView generalExceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception ex) {
       String errorLog = String.format("web请求[%s]发生异常:%s",  new Object[]{request.getServletPath(), ex.getMessage()});
        this.logger.error(errorLog, ex);
       ModelAndView mav =  new ModelAndView();
       String errorMsg  =  "系统出错了";
        if(ex  instanceof   GenericException  || ex  instanceof  EcouponException){
           errorMsg  =  ex.getMessage();
       }
       mav.addObject("msg", errorMsg);
       String name = ex.getClass().getName();
       String path =  this.exceptionMappings.getProperty(name);
       String wrapperPath = StringUtils.isEmpty(path)?defaultErrorView:path;
       mav.setViewName(wrapperPath);
        return mav;
   }


}
最后配置该bean:

<bean class="com.me.common.exception.XExceptionResolver">
       <!-- view name resolved using bean of type InternalResourceViewResolver (declared in mvc-view-config.xml) -->
       <property name="defaultErrorView" value="exception"/>
       <!-- needed otherwise exceptions won't be logged anywhere -->
       <property name="exceptionMappings">
           <props>
               <prop key="com.me.common.exception.GenericException">error/error</prop>
               <prop key="com.me.common.exception.EcouponException">error/error</prop>
               <prop key="java.lang.Exception">error/error</prop>
           </props>
       </property>
   </bean>

【2021年,将Spring全家桶的课程进行Review,确保不再有课程的顺序错乱,从而导致学员看不懂。进入2022年,将Spring的课程进行整理,整理为案例精讲的系列课程,并开始加入高阶Spring Security等内容,一步步手把手教你从零开始学会应用Spring,课件将逐步进行上传,敬请期待!】 本课程是Spring全家桶系列课程的第三部分Spring Boot,Spring案例精讲课程以真实场景、项目实战为导向,循序渐进,深入浅出的讲解Java网络编程,助力您在技术工作中更进一步。 本课程聚焦Spring Boot核心知识点:整合Web(如:JSP、Thymeleaf、freemarker等的整合)的开发、全局异常处理、配置文件的配置访问、多环境的配置文件设置、日志Logback及slf4j的使用、国际化设置及使用, 并在最后以一个贯穿前后台的Spring Boot整合Mybatis的案例为终奖,使大家快速掌握Spring的核心知识,快速上手,为面试、工作都做好充足的准备。 由于本课程聚焦于案例,即直接上手操作,对于Spring的原理等不会做过多介绍,希望了解原理等内容的需要通过其他视频或者书籍去了解,建议按照该案例课程一步步做下来,之后再去进一步回顾原理,这样能够促进大家对原理有更好的理解。 【通过Spring全家桶,我们保证你能收获到以下几点】 1、掌握Spring全家桶主要部分的开发、实现2、可以使用Spring MVC、Spring Boot、Spring Cloud及Spring Data进行大部分的Spring开发3、初步了解使用微服务、了解使用Spring进行微服务的设计实现4、奠定扎实的Spring技术,具备了一定的独立开发的能力  【实力讲师】 毕业于清华大学软件学院软件工程专业,曾在Accenture、IBM等知名外企任管理及架构职位,近15年的JavaEE经验,近8年的Spring经验,一直致力于架构、设计、开发及管理工作,在电商、零售、制造业等有丰富的项目实施经验  【本课程适用人群】如果你是一定不要错过!  适合于有JavaEE基础的,如:JSP、JSTL、Java基础等的学习者没有基础的学习者跟着课程可以学习,但是需要补充相关基础知识后,才能很好的参与到相关的工作中。 【Spring全家桶课程共包含如下几门】 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值