統一處理一個Controller中拋出的異常


一、前言

  在搭建工程的時候,統一處理拋出的異常會讓我們的程序看起來更加整潔,有序,方便管理。所以我打算在我的項目中配置使用統一異常處理。

二、步驟

  一般來說有三個步驟:

  1. 定義錯誤

  2. 將錯誤映射成異常

  3. 處理異常,然后讓異常以自己需要的形式返回到前端。

三、 具體實現

1. 定義錯誤

 

public enum Error {
    NO_TOKEN_FOUND(1, "No token found"),
    NO_VALID_TOKEN(2, "Token is not valid");
    
    public final int errorCode;
    public final String errorMessage;
    
    private Error(int errorCode, String errorMessage) {
        this.errorCode = errorCode;
        this.errorMessage = errorMessage;
    }
    
    public int getErrorCode() { return errorCode; }
    
    public String getErrorMessage() { return errorMessage; }
}

 

2. 將錯誤映射成異常

public class RequestException extends Exception{
    private static final long serialVersionUID = 1L;
    private final Error error;
    
    public RequestException(Error err) {
        super(err.getErrorMessage());
        this.error = err;
    }
    
    public Error getError() { return error; }
}

3. 處理異常,然后讓異常以自己需要的形式返回到前端。(這里我是直接返回的是Map形式的數據)

    @ControllerAdvice
    public class ExceptionHandle {

        @ExceptionHandler(value = Exception.class)
        @ResponseBody
        public Map<String, String> handler( Exception e){
       
           RequestException requestException = (RequestException) e;
           Map map = new HashMap<String, String>();
           map.put(requestException.getError().errorCode,requestException.getError().errorMessage);
           return map;
           
        }
    }

4. 使用我們定義的異常

 

     User user = userRespository.findOne(userId);
        
        if (user == null) {
            throw new RequestException(Error.USER_DOES_NOT_EXIST);//這里會產生一個新的異常,然后步驟三的操作會捕捉到異常,以我們定義的形式返回到前端
        }

四、擴展延伸

  • @ExceptionHandler:統一處理某一類異常,從而能夠減少代碼重復率和復雜度
  • @ControllerAdvice:異常集中處理,更好的使業務邏輯與異常處理剝離開
  • @ResponseStatus:可以將某種異常映射為HTTP狀態碼

@ExceptionHandler

源碼如下:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
    Class<? extends Throwable>[] value() default {};
}

該注解作用對象為方法,並且在運行時有效,value()可以指定異常類。由該注解注釋的方法可以具有靈活的輸入參數(詳細參見Spring API):

  • 異常參數:包括一般的異常或特定的異常(即自定義異常),如果注解沒有指定異常類,會默認進行映射。
  • 請求或響應對象 (Servlet API or Portlet API): 你可以選擇不同的類型,如ServletRequest/HttpServletRequest或PortleRequest/ActionRequest/RenderRequest
  • Session對象(Servlet API or Portlet API): HttpSession或PortletSession。
  • WebRequest或NativeWebRequest 
  • Locale
  • InputStream/Reader 
  • OutputStream/Writer 
  • Model

方法返回值可以為:

    • ModelAndView對象
    • Model對象
    • Map對象
    • View對象
    • String對象
    • 還有@ResponseBody、HttpEntity<?>或ResponseEntity<?>,以及void

 

@ControllerAdvice

源碼如下:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
    @AliasFor("basePackages")
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<?>[] assignableTypes() default {};

    Class<? extends Annotation>[] annotations() default {};
}

該注解作用對象為TYPE,包括類、接口和枚舉等,在運行時有效,並且可以通過Spring掃描為bean組件。其可以包含由@ExceptionHandler、@InitBinder 和@ModelAttribute標注的方法,可以處理多個Controller類,這樣所有控制器的異常可以在一個地方進行處理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM