springboot springmvc 全局異常處理

主要利用 spring-webmvc提供的@ControllerAdvice註解和@ExceptionHandler註解,所以springwebmvc的依賴必不可少。
@ControllerAdvice作用在類上,表明使用該類對controller中拋出的異常進行捕獲處理。
@ExceptionHandler作用在方法上,需要指定異常的字節碼數組,以便說明該方法是用來處理哪些異常。
下面我們用一個demo來幫助我們理解這兩個註解。

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;

@ControllerAdvice
public class CommonExceptionHandler {

    @ExceptionHandler(IOException.class)
    @ResponseBody
    public String handleIOException(IOException ioException) {
        //IOException會被自動注入
        return ioException.getMessage();
    }
    
    @ExceptionHandler({IOException.class,RuntimeException.class})
    @ResponseBody
    public String handleIOException(IOException ioException,RuntimeException runtimeException) {
        String msg1 = ioException.getMessage();
        String msg2 = runtimeException.getMessage();
        return "";
    }
}

上面的代碼讓我們初步瞭解了全局的異常捕獲處理,但是和實際開發中的異常處理還是差很多,下面我們按步驟演示一個完整的異常處理。
注:下面的代碼爲了方便使用了lombok。

1. 定義ExceptionResult類(VO),因爲項目是前後端分離,出現異常後,我們需要將一些必要的異常信息返回給前端展示。一般定義一個狀態碼,異常的提示信息,時間戳等等,這些字段根據自己的需要添加。
@Data
public class ExceptionResult {
    private int status;
    private String message;
    private Long timestamp;

	// ExceptionEnums是一個枚舉類,管理我們項目中自定義的異常信息和狀態碼
    public ExceptionResult(ExceptionEnums exceptionEnums) {
        this.status = exceptionEnums.getCode();
        this.message = exceptionEnums.getMsg();
        this.timestamp = System.currentTimeMillis();
    }
}

2. 自定義ExceptionEnums枚舉類,管理我們項目中自定義的異常信息和狀態碼。

@Getter
@AllArgsConstructor
public enum ExceptionEnums {
    USERNAME_CANNOT_BE_NULL(400,"用戶名不能爲空"),
    PASSWORD_CANNOT_BE_NULL(401,"密碼不能爲空");
    private final int code;
    private final String msg;
}

3. 自定義CustomException異常類,有了該異常類,我們就可以在全局異常處理器中捕獲他,進行處理。該異常類需要繼承RuntimeException而不是Exception。因而該自定義異常可以直接拋出,而不用在controller方法上聲明。

@Getter
@AllArgsConstructor
public class LyException extends RuntimeException{
	// 在拋該異常實例化的時候需要傳入我們的枚舉類對象,這樣做的目的是攜帶我們自定義的異常信息和狀態碼
    private ExceptionEnums exceptionEnums;
}

4. 創建全局異常處理器,捕獲我們第三步自定義的異常,實現通用的異常處理。

@ControllerAdvice
public class CommonExceptionHandler {

    @ExceptionHandler(CustomException.class)
    public ResponseEntity<ExceptionResult> handleException(CustomException customException) {
    	// 獲取存儲自定義異常信息和狀態碼的枚舉對象
        ExceptionEnums exceptionEnums = customException.getExceptionEnums();
        return ResponseEntity.status(exceptionEnums.getCode()).body(new ExceptionResult(exceptionEnums));
    }

}

關於ResponseEntity<T>,使用這個類我們可以設置響應行的status,同時可以序列化不同類型的數據到響應體中。

5. 在controller方法中需要的地方拋出異常。這裏注意一點,如果service層出現異常,不要try catch,直接向上拋到controller這一層,不然全局異常處理器捕獲不到。

@Controller("user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("login")
    public ResponseEntity<Item> login(User user) {
        if (StringUtils.isBlank(user.getUsername)) {
            throw new CustomException(ExceptionEnums.USERNAME_CANNOT_BE_NULL);
        }
        user = userService.login(user);
        return ResponseEntity.ok(user);
    }
}

6.測試我們的接口,就故意不傳username,看一下效果。

在這裏插入圖片描述

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