在項目中,難免會出現各種各樣的異常,我們希望異常信息盡可能詳細,包括響應狀態碼,響應的字符串異常信息,甚至操作時間等等,這樣可以方便地快速定位到發生異常的位置.所以,一個項目中對於異常的處理就顯得尤為重要.那么,小編就以SpringBoot框架,通過代碼實例展示統一異常的處理方式.
1.首先我們簡單搭建一個SpringBoot框架的項目,項目名稱是exceptionhandler(異常處理)
2.導入相關依賴
導入lombok依賴,提供@getter注解
導入日期工具類JodaTime,提供DateTime.now()方法
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--日期工具類:JodaTime--> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
3.編寫application.yml配置文件
注意這里添加了訪問路徑前綴
server: port: 8082 servlet: context-path: /exception
4.編寫SpringBoot的啟動類
package com.exception; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ExceptionApplication { public static void main(String[] args) { SpringApplication.run(ExceptionApplication.class, args); } }
5.編寫異常枚舉類
異常枚舉類中,應該列舉出項目可能出現的所有異常類型,這里只拿數學計算異常舉例
package com.exception.enums; import lombok.Getter; /** * 異常枚舉類 */ @Getter public enum ExceptionEnum { ARTITHMETIC(500, "數學計算異常"); private Integer status; private String message; ExceptionEnum(Integer status, String message) { this.status = status; this.message = message; } }
6.編寫自定義異常類
自定義異常類繼承RuntimeException,同時RuntimeException繼承Exception類,而Exception又繼承Throwable類,super方法最終也是Throwable中的方法
package com.exception.exceptions; import com.exception.enums.ExceptionEnum; import lombok.Getter; /** * 自定義異常類 */ @Getter public class SelfDefinedException extends RuntimeException { private Integer status; public SelfDefinedException(ExceptionEnum exceptionEnum) { super(exceptionEnum.getMessage()); this.status = exceptionEnum.getStatus(); } public SelfDefinedException(ExceptionEnum exceptionEnum, Throwable cause) { super(exceptionEnum.getMessage(), cause); this.status = exceptionEnum.getStatus(); } }
7.編寫統一異常返回結果類
package com.exception.entity; import com.exception.exceptions.SelfDefinedException; import lombok.Getter; import org.joda.time.DateTime; /** * 統一異常返回結果類 */ @Getter public class ExceptionResult { private Integer status; private String message; private String timestamp; public ExceptionResult(SelfDefinedException e) { this.status = e.getStatus(); this.message = e.getMessage(); this.timestamp = DateTime.now().toString("yyyy-MM-dd HH:mm:ss"); } }
8.編寫統一異常攔截類
需注意兩個spring注解的作用:
@ControllerAdvice:此注解默認情況下,會攔截所有加了@Controller注解的類
@ExceptionHandler():此注解用在方法上,括號內聲明要處理的異常類型,可以指定多個,這里我們指定的是自定義異常
package com.exception.advice; import com.exception.entity.ExceptionResult; import com.exception.exceptions.SelfDefinedException; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; /** * 統一異常攔截類 */ @ControllerAdvice @Slf4j public class BasicExceptionAdvice { @ExceptionHandler(SelfDefinedException.class) public ResponseEntity<ExceptionResult> handlerException(SelfDefinedException e) {//參數類型與要處理的異常類型必須匹配 return ResponseEntity.status(e.getStatus()).body(new ExceptionResult(e));//body中的對象必須和ResponseEntity中的對象一致 } }
9.編寫測試類
package com.exception.controller; import com.exception.enums.ExceptionEnum; import com.exception.exceptions.SelfDefinedException; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j public class TestController { @GetMapping("/test") public ResponseEntity<String> login() { try { Integer tempValue = 10 / 0; } catch (Exception e) { throw new SelfDefinedException(ExceptionEnum.ARTITHMETIC);//catch捕獲異常后,這里throw拋出異常並未處理,所以后面的代碼不會執行 } return ResponseEntity.ok("沒發現異常,返回正確的字符串"); } }
10.測試結果
通過IDEA自帶的HTTP Client進行測試,觀察響應結果如下.這樣我們就得到了
總結:
因為項目中會出現各種各樣的異常,所以我們通過一個異常枚舉類將所有的異常進行列舉.我們希望捕獲自己定義的異常,所以編寫了一個自定義異常類,同時我們希望響應的異常結果規則且詳細,所以通過一個統一異常結果類來實現.最重要的是,我們還需要一個異常攔截類,這樣在我們拋出自定義異常的時候,這個異常攔截類能夠進行攔截,並將我們定義好的響應結果(也就是異常體所有信息)返回.