1. 程式人生 > >springmvc自定義全域性異常處理

springmvc自定義全域性異常處理

springmvc全域性異常

  • 實現步驟
  • 在web層下新建一個類
    • 通過實現spring的HandlerExceptionResolver介面來捕獲所有的異常。
    • 寫一個異常處理類實現HandlerExceptionResolver介面
  • 如下:

    public class MvcWholeExceptionResolver implements HandlerExceptionResolver
    {
    private static final Logger logger = Logger.getLogger(MvcWholeExceptionResolver.class);
    //mvc捕獲異常
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,Exception exception)
    {
    //可以在mv裡放異常的頁面地址和異常的資訊
    ModelAndView mv=new ModelAndView();
    if(exception!=null)
    {
    //自定義封裝的業務異常丟擲類
    BizException bizException = null;
    logger.warn("MVC全域性異常捕捉類捕捉到異常");
    if(exception instanceof LoginException)
    {
    logger.warn("捕捉到業務異常子類登入異常丟擲類:LoginException");
    bizException=(BizException)exception;

              }else{
                  logger.warn("捕捉到系統未知異常:UNCLASSFY_EXCEPTION");
                  logger.warn("UNCLASSFY_EXCEPTION:   "+exception);
                  bizException=BizException.UNCLASSFY_EXCEPTION;
                  //要捕捉更多業務類的異常,在自定義更多像LoginException的子類即可,或者在建立像BizException一樣的類,這裡就舉這兩個例子,其它仿照拓展
    
              }
              logger.warn("異常程式碼:"+bizException.getCode()+"   異常資訊:"+bizException.getMessage());
              //如果前端是通過ajax請求的後臺丟擲異常,那麼無需返回異常頁面,只需要返回異常資訊,方法如下:
              //在request作用域裡儲存異常的程式碼和資訊
              request.setAttribute(UsualConstants.RETURN_ERROR_CODE_KEY, bizException.getCode());
              request.setAttribute(UsualConstants.RETURN_ERROR_MSG_KEY, bizException.getMessage());
              //在通過轉發到controller裡的方法,返回@ResponsBody方式,前臺ajax裡自然會捕捉到,如下:
              try{
                  logger.warn("轉發到ajax的統一異常處理方法");
                  request.getRequestDispatcher("/manage/login/jsonException").forward(request, response);
    
              }catch(Exception e){
                  logger.warn("轉發到ajax統一異常處理出錯");
                  e.printStackTrace();
              }
          }
          //雖然ajax的異常在前面已經返回給前端了,但是還會執行到這裡,如果在mv裡沒有加任何東西或者只加異常資訊,return時會報錯,但不影響前端,前端已經捕捉到ajax的異常了
          //如果在mv裡有加入跳轉的異常頁面,那麼前端也會跳轉,根據具體需要要不要跳轉具體異常頁面,這裡不放具體頁面
          mv.addObject(UsualConstants.RETURN_ERROR_MSG_KEY,bizException.getMessage());
          return mv;
      }
    }
    • 在springMVC的配置檔案中要指定全域性異常處理類的位置,如下:

    • ajax的統一異常處理方法,如下:

      @RequestMapping("jsonException")
      @ResponseBody
      public ResultJson jsonException(HttpServletRequest request,Map map)
      {
      logger.warn("統一異常處理方法,取出異常程式碼和異常資訊封裝到ResultJson,方法通過@ResponseBody方式返回ResultJson,前臺得到資訊為json格式");
      Integer errorCode=(Integer)request.getAttribute(UsualConstants.RETURN_ERROR_CODE_KEY);
      String errorMsg=(String)request.getAttribute(UsualConstants.RETURN_ERROR_MSG_KEY);
      ResultJson rj=new ResultJson();
      rj.setKey(errorCode);
      rj.setMessage(errorMsg);
      logger.warn("返回的ResultJson物件為:"+rj);
      return rj;
      }
  • 在service層或者dao層裡,自定義統一業務異常丟擲類,如下:

    package cn.hj.yzp_app1.common.tools.exception;
    import cn.hj.yzp_app1.common.tools.constantsTools.StatusConstants;
    //業務異常基類,所有業務異常都必須繼承於此異常
    public class BizException extends RuntimeExceptionAware
    {
    //RuntimeExceptionAware是自定義的執行時異常類,下面例子會貼出程式碼
    private static final long serialVersionUID = -697081422076812812L;
    //定義系統未知異常
    public static final BizException UNCLASSFY_EXCEPTION = new BizException(StatusConstants.UNCLASSFY_EXCEPTION_CODE, StatusConstants.UNCLASSFY_EXCEPTION_MSG);

      //異常編號
      protected int code;
      //異常資訊
      protected String msg;
    
      //例項化異常
      public BizException newInstance(String message, Object... args) {
          return new BizException(this.code, message, args);
      }
    
      public BizException(int code, String message, Object... args) 
      {
          //父級變數
          super(message);
          this.code = code;
          this.msg = String.format(message, args);
      }
    
      public BizException(String message, Throwable cause) {
          super(message, cause);
      // TODO Auto-generated constructor stub
      }
      public BizException(String message) {
          super(message);
      // TODO Auto-generated constructor stub
      }
      public BizException(Throwable cause) {
          super(cause);
      // TODO Auto-generated constructor stub
      }
      public BizException() {
          super();
      // TODO Auto-generated constructor stub
      }
      /**
      * @return the code
      */
      public int getCode() {
          return code;
      }
      /**
       * @param code the code to set
      */
      public void setCode(int code) {
          this.code = code;
      }
      /**
      * @return the msg
      */
      public String getMsg() {
          return msg;
      }
      /**
      * @param msg the msg to set
      */
      public void setMsg(String msg) {
          this.msg = msg;
      }
      /**
      * @return the serialversionuid
      */
      public static long getSerialversionuid() {
          return serialVersionUID;
      }
    }
  • 執行時異常處理類

    package cn.hj.yzp_app1.common.tools.exception;
    public class RuntimeExceptionAware extends RuntimeException{
    //RuntimeException是系統的執行時異常類
    private static final long serialVersionUID = -4896922247366620859L;

      public RuntimeExceptionAware() {
          super();
      // TODO Auto-generated constructor stub
      }
    
      public RuntimeExceptionAware(String message, Throwable cause) {
          super(message, cause);
          // TODO Auto-generated constructor stub
      }
    
      public RuntimeExceptionAware(String message) {
          super(message);
          // TODO Auto-generated constructor stub
      }
    
      public RuntimeExceptionAware(Throwable cause) {
          super(cause);
          // TODO Auto-generated constructor stub
      }
    }
  • 自定義的登入異常丟擲類:LoginException,如下:

    package cn.hj.yzp_app1.common.tools.exception;
    import org.apache.log4j.Logger;
    import cn.hj.yzp_app1.common.tools.exception.BizException;
    //自定義登入異常
    public class LoginException extends BizException{
    //屬於業務異常BizException的子類
    private static final long serialVersionUID = -6160637178050783184L;
    private static final Logger logger = Logger.getLogger(LoginException.class);
    public LoginException() {
    super();
    // TODO Auto-generated constructor stub
    }

      public LoginException(int code, String message, Object... args) {
          super(code, message, args);
      // TODO Auto-generated constructor stub
      }
    
      public LoginException(String message, Throwable cause) {
          super(message, cause);
          // TODO Auto-generated constructor stub
      }
    
      public LoginException(String message) {
          super(message);
          // TODO Auto-generated constructor stub
      }
    
      public LoginException(Throwable cause) {
          super(cause);
          // TODO Auto-generated constructor stub
      }
    }
  • 丟擲異常例子,如下:

    @RequestMapping("loginVerify")
    @ResponseBody
    public ResultJson loginVerify(UserExtend user,HttpSession session) {
    ResultJson rj=new ResultJson();
    try{
    userServiceImpl.login(user);
    }catch(NullPointerException e){
    //如登入操作時,捕獲到空指標異常了,就可以認為是登入異常,丟擲後在MvcWholeExceptionResolver裡就可以捕捉到,然後在返回前端提示給使用者
    throw new LoginException(StatusConstants.NO_LOGINMSG_CODE,StatusConstants.NO_LOGINMSG_MSG);
    }
    }