使用@ControllerAdvice + @ExceptionHandler建立全局異常攔截

  1. @ControllerAdvice 註解定義全局異常處理類
    @ControllerAdvice
    public class GlobalExceptionHandler {
    }
    
  2. @ExceptionHandler 註解聲明異常處理方法
    @ControllerAdvice
    public class GlobalExceptionHandler{
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public String handleException() {
            ex.printStackTrace(); 
            return "fail";
        }
    }
    
    方法handleException()會處理所有Controller層拋出的Exception及其子類的異常,Controller層就不需要單獨處理異常了。
    但如上代碼只能處理 Controller 層的異常,對於未進入Controller的異常,如Interceptor(攔截器)層的異常,Spring 框架層的異常無效,還是會將錯誤直接返回給用戶。對此,只需要在配置文件中添加:
    spring.mvc.throw-exception-if-no-handler-found=true
    spring.resources.add-mappings=false
    
  3. 被 @ExceptionHandler 註解的方法還可以聲明很多種參數類型,具體可以參考文檔:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html
    這裏我選擇了httpServletRequest, HttpServletResponse httpServletResponse, Exception ex三個參數,應用如下:
    @ControllerAdvice
    public class GlobalExceptionHandler{
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public CommonReturnType handleException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Exception ex) {
            ex.printStackTrace(); // 線上環境替換爲對應的log
            Map<String,Object> responseData = new HashMap<>();
            if( ex instanceof BusinessException){
                BusinessException businessException = (BusinessException)ex;
                responseData.put("errCode",businessException.getErrCode());
                responseData.put("errMsg",businessException.getErrMsg());
            }else if(ex instanceof ServletRequestBindingException){
                responseData.put("errCode",BusinessError.UNKNOWN_ERROR.getErrCode());
                responseData.put("errMsg","url綁定路由問題");
            }else if(ex instanceof NoHandlerFoundException){
                responseData.put("errCode",BusinessError.UNKNOWN_ERROR.getErrCode());
                responseData.put("errMsg","沒有找到對應的訪問路徑");
            }else{
                responseData.put("errCode", BusinessError.UNKNOWN_ERROR.getErrCode());
                responseData.put("errMsg", BusinessError.UNKNOWN_ERROR.getErrMsg());
            }
            return CommonReturnType.create(responseData,"fail");
        }
    }
    

如此,所有的 Controller 層的異常日誌都可以通過GlobalExceptionHandler 記錄。Controller 層也不需要在手動記錄異常日誌了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章