SpringBoot 實戰 (十四) | 統一處理異常
微信公眾號:一個優秀的廢人
前言
如題,今天介紹 SpringBoot 是如何統一處理全域性異常的。SpringBoot 中的全域性異常處理主要起作用的兩個註解是 @ControllerAdvice 和 @ExceptionHandler ,其中 @ControllerAdvice 是元件註解,添加了這個註解的類能夠攔截 Controller 的請求,而 ExceptionHandler 註解可以設定全域性處理控制裡的異常型別來攔截要處理的異常。 比如:@ExceptionHandler(value = NullPointException.class) 。
準備工作
- SpringBoot 2.1.3
- IDEA
- JDK 8
依賴配置
<dependencies> <!-- JPA 依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- web 依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- mysql 連線類 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- lombok 依賴 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- 單元測試依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
配置檔案
spring: # 資料庫相關 datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=true username: root password: 123456 jpa: hibernate: ddl-auto: update#ddl-auto:設為 create 表示每次都重新建表 show-sql: true
返回的訊息類
public class Message<T> implements Serializable { /** * 狀態碼 */ private Integer code; /** * 返回資訊 */ private String message; /** * 返回的資料類 */ private T data; /** * 時間 */ private Long time; // getter、setter 以及 構造方法略。。。 }
工具類
用於處理返回的資料以及資訊類,程式碼註釋很詳細不說了。
public class MessageUtil { /** * 成功並返回資料實體類 * @param o * @param <E> * @return */ public static <E>Message<E> ok(E o){ return new Message<>(200, "success", o, new Date().getTime()); } /** * 成功,但無資料實體類返回 * @return */ public static <E>Message<E> ok(){ return new Message<>(200, "success", null, new Date().getTime()); } /** * 失敗,有自定義異常返回 * @param code * @param msg * @return */ public static <E>Message<E> error(Integer code,String msg){ return new Message<>(code, msg, null, new Date().getTime()); } }
自定義異常
通過繼承 RuntimeException ,宣告 code 用於定義不同型別的自定義異常。主要是用於異常攔截出獲取 code 並將 code 設定到訊息類中返回。
public class CustomException extends RuntimeException{ /** * 狀態碼 */ private Integer code; public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public CustomException(Integer code, String message){ super(message); this.code = code; } }
異常攔截類
通過加入 @RestControllerAdvice 來宣告該類可攔截 Controller 請求,同時在 handle方法加入 @ExceptionHandler 並在該註解中指定要攔截的異常類。
@RestControllerAdvice // 控制器增強處理(返回 JSON 格式資料),添加了這個註解的類能被 classpath 掃描自動發現 public class ExceptionHandle { @ExceptionHandler(value = Exception.class) // 捕獲 Controller 中丟擲的指定型別的異常,也可以指定其他異常 public <E>Message<E> handler(Exception exception){ if (exception instanceof CustomException){ CustomException customException = (CustomException) exception; return MessageUtil.error(customException.getCode(), customException.getMessage()); } else { return MessageUtil.error(120, "異常資訊:" + exception.getMessage()); } } }
這裡只對自定義異常以及未知異常進行處理,如果你在某方法中明確知道可能會丟擲某個異常,可以加多一個特定的處理。比如說你明確知道該方法可能丟擲 NullPointException 可以追加 NullPointException 的處理:
if (exception instanceof CustomException){ CustomException customException = (CustomException) exception; return MessageUtil.error(customException.getCode(), customException.getMessage()); } else if (exception instanceof NullPointException ){ return MessageUtil.error(500, "空指標異常信!"); } else { return MessageUtil.error(120, "異常資訊:" + exception.getMessage()); }
controller 層
@RestController @RequestMapping("/student") public class StudentController { @Autowired private StudentService studentService; @GetMapping("/{id}") public Message<Student> findStudentById(@PathVariable("id") Integer id){ if (id < 0){ //測試自定義錯誤 throw new CustomException(110, "引數不能是負數!"); } else if (id == 0){ //硬編碼,為了測試 Integer i = 1/id; return null; } else { Student student = studentService.findStudentById(id); return MessageUtil.ok(student); } } }
完整程式碼
https://github.com/turoDog/De...
如果覺得對你有幫助,請給個 Star 再走唄,非常感謝。
Postman 測試
訪問 http://localhost :8080/student/5 測試正常返回資料結果。
訪問 http://localhost :8080/student/0 測試未知異常的結果。
訪問 http://localhost :8080/student/-11 測試自定義異常的結果。
後語
如果本文對你哪怕有一丁點幫助,請幫忙點好看。你的好看是我堅持寫作的動力。
另外,關注之後在傳送 1024 可領取免費學習資料。資料內容詳情請看這篇舊文: Python、C++、Java、Linux、Go、前端、演算法資料分享