• Web层通用数据处理之统一异常处理@ExceptionHandler


      实际开发过程中会遇到对dao层、service层和controller层抛出的异常统一处理,对每个模块的方法进行异常处理也能解决问题,但这样是不合理的,并且代码看起来也不雅观,这时就可以使用@ExceptionHandler对Web层进行统一异常处理,让异常由下往上(dao—>service—>controller)抛出。代码如下:

    import com.sand.base.core.common.BaseCommon;
    import com.sand.base.core.entity.ResultEntity;
    import com.sand.base.enums.ResultEnum;
    import com.sand.base.exception.LsException;
    import com.sand.base.util.ResultUtil;
    import com.sand.base.util.editor.DateEditor;
    import com.sand.base.util.editor.StringEditor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.http.converter.HttpMessageNotReadableException;
    import org.springframework.web.bind.MissingServletRequestParameterException;
    import org.springframework.web.bind.WebDataBinder;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.InitBinder;
    import org.springframework.web.bind.annotation.ModelAttribute;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.util.Date;
    import java.util.Objects;
    
    /**
     * 功能说明:Web层通用数据处理
     * 开发人员:@author liusha
     * 开发日期:2019/8/26 21:43
     * 功能描述:定义所有控制器的父控制器,进行属性绑定、数据转换、异常处理
     */
    @Slf4j
    public class BaseController extends BaseCommon {
      protected HttpSession session;
      protected HttpServletRequest request;
      protected HttpServletResponse response;
    
      /**
       * 属性访问器
       *
       * @param session  session
       * @param request  request
       * @param response response
       */
      @ModelAttribute
      public void modelAttribute(HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        this.session = session;
        this.request = request;
        this.response = response;
      }
    
      /**
       * 属性编辑器
       *
       * @param binder 数据绑定
       */
      @InitBinder
      public void initBinder(WebDataBinder binder) {
        // Date类型转换,几乎支持所有的日期类型
        binder.registerCustomEditor(Date.class, new DateEditor());
        // String类型转换,将所有传递进来的String进行HTML编码,防止XSS攻击
        binder.registerCustomEditor(String.class, new StringEditor());
      }
    
      /**
       * 顶级异常处理
       *
       * @param e 异常
       * @return 响应客户端
       */
      @ExceptionHandler(Exception.class)
      public ResultEntity handleException(Exception e) {
        errorLog(e);
        return ResultUtil.error();
      }
    
      /**
       * 自定义异常处理
       *
       * @param e 异常
       * @return 响应客户端
       */
      @ExceptionHandler(LsException.class)
      public ResultEntity handleLsException(LsException e) {
        errorLog(e);
        return ResultUtil.info(e.getCode(), e.getMessage());
      }
    
      /**
       * 参数缺失处理
       *
       * @param e 异常
       * @return 响应客户端
       */
      @ExceptionHandler(MissingServletRequestParameterException.class)
      public ResultEntity handleMissingParamException(MissingServletRequestParameterException e) {
        errorLog(e);
        return ResultUtil.error(ResultEnum.PARAM_MISSING_ERROR);
      }
    
      /**
       * 读取方法处理
       *
       * @param e 异常
       * @return 响应客户端
       */
      @ExceptionHandler(HttpMessageNotReadableException.class)
      public ResultEntity handleMessageNotReadableException(HttpMessageNotReadableException e) {
        errorLog(e);
        return ResultUtil.error(ResultEnum.READ_METHOD_ERROR);
      }
    
      /**
       * 打印出错log
       *
       * @param e 异常
       */
      private void errorLog(Exception e) {
        StackTraceElement element = e.getStackTrace()[0];
        if (e instanceof LsException) {
          log.info("异常位置:{}.{},第{}行,原因:{}", element.getClassName(), element.getMethodName(), element.getLineNumber(), e.getMessage());
          if (!Objects.isNull(e.getCause())) {
            StackTraceElement cause = e.getCause().getStackTrace()[0];
            log.info("起因:{}.{},第{}行,原因:{}", cause.getClassName(), cause.getMethodName(), cause.getLineNumber(), e.getCause().getMessage());
          }
        } else {
          log.error("错误位置:{}.{},第{}行,错误原因:{}", element.getClassName(), element.getMethodName(), element.getLineNumber(), e.getClass().getName());
        }
        log.error("错误信息:" + e);
      }
    
    }

      需要注意的是,这种处理方式只对当前controller有效,也就是只有当controller继承了BaseController才能捕获到异常。如果希望没有继承BaseController的controller也能进行异常捕获,就需要新建一个@ControllerAdvice切面类配合@ExceptionHandler进行全局异常处理(值得注意的是,其它所有的切面类需将异常抛出而不是捕获处理,异常处理流程由统一异常处理类去完成,方便排查问题)。

      我这里只列出了其中几种异常,异常种类远远不止这些,可以参考API文档进行选择自己需要的异常http://tool.oschina.net/apidocs/apidoc?api=Spring-3.1.1

        千万不要试图去研究 研究了很久都整不明白的东西,或许是层次不到,境界未到,也或许是从未在实际的应用场景接触过,这种情况下去研究,只会事倍功半,徒劳一番罢了。能做的就是不断的沉淀知识,保持一颗积极向上的学习心态,相信终有一天所有的困难都会迎刃而解。
  • 相关阅读:
    Element+Vue.js 选择器常用属性
    常用xml头文件
    【链接】调查显示:超20%美国大学生曾花学生贷款投
    Quartz遇到的问题
    List去重
    SpringDataJPA
    IDEA:Error during artifact deployment. See server log for details.详解
    Quartz定时任务
    多线程条件通行工具——CountDownLatch
    多线程同步工具——Lock
  • 原文地址:https://www.cnblogs.com/54hsh/p/11453493.html
Copyright © 2020-2023  润新知