SpringBoot中異常處理
- 2022 年 4 月 28 日
- 筆記
- springboot
一、背景
在我們編寫程序的過程中,程序中可能隨時發生各種異常,那麼我們如何優雅的處理各種異常呢?
二、需求
1、攔截系統中部分異常,返回自定義的響應。
比如:
系統發生HttpRequestMethodNotSupportedException
異常,我們需要返回如下信息。
http的狀態碼:返回 405
{
code: 自定義異常碼,
message: 錯誤消息
}
2、實現自定義異常的攔截
攔截我們自己寫的 BizException
三、編寫一些異常基礎代碼
1、引入jar包
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
注意:
引入spring-boot-starter-validation
是為了驗證請求的中的參數,然後當參數不滿足時拋出異常。
2、定義一個自定義異常
public class BizException extends RuntimeException {
public BizException() {
}
public BizException(String message) {
super(message);
}
public BizException(String message, Throwable cause) {
super(message, cause);
}
public BizException(Throwable cause) {
super(cause);
}
public BizException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
3、編寫一個簡單的控制層
@RestController
@RequestMapping("exception")
public class ExceptionTestController {
static class Req {
@NotBlank
public String password;
}
@PostMapping("password")
public String checkPassword(@Validated @RequestBody Req req) {
if (Objects.equals(req.password, "exception")) {
throw new BizException("密碼傳遞的是exception字符串");
}
return "當前密碼,password: " + req.password;
}
}
解釋
提供一個 /exception/password
api,需要傳遞一個password
參數
1、當不傳遞 password 參數時將拋出MethodArgumentNotValidException異常。
2、當password傳遞exception參數時,則拋出BizException異常。
4、測試
1、不傳遞password參數響應是什麼
1、使用默認的DefaultHandlerExceptionResolver處理
這個類DefaultHandlerExceptionResolver
是默認自動配置的。
從上圖中可以看出有一個默認字段的返回值
2、使用ResponseEntityExceptionHandler處理
1、編寫異常處理代碼-使用默認的邏輯
@RestControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
// 此處自定義返回值
return super.handleMethodArgumentNotValid(ex, headers, status, request);
}
}
可以看到handleMethodArgumentNotValid
方法直接調用父類的方法,即使用默認的處理方式。
從上圖中可以看出返回值是空
2、編寫異常處理代碼-返回值返回自定義內容
@Component
@RestControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
// 此處自定義返回值
return super.handleMethodArgumentNotValid(ex, headers, status, request);
}
@Override
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
Set<HttpMethod> supportedMethods = ex.getSupportedHttpMethods();
// 自定義請求返回值
Map<String, Object> body = new HashMap<>(4);
body.put("code", "錯誤碼");
body.put("message", "當前請求的方法不支持,支持的請求方法為:" + supportedMethods);
return new ResponseEntity<>(body, headers, status);
}
}
由上面的代碼可知handleHttpRequestMethodNotSupported
方法返回了自定義的body。
從上圖中可以看出,返回了我們自己定義的返回值。
2、password參數傳遞exception
1、使用ResponseEntityExceptionHandler或DefaultHandlerExceptionResolver處理
由上圖可知返回結果不對,我們需要自定義返回結果。
2、返回自定義異常
1、編寫BizException處理代碼
@RestControllerAdvice
public class BizExceptionHandler {
@ExceptionHandler(BizException.class)
public ResponseEntity<Object> handleBizException(BizException exception) {
// 自定義請求返回值
Map<String, Object> body = new HashMap<>(4);
body.put("code", "錯誤碼");
body.put("message", "異常信息為:" + exception.getMessage());
return new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
2、測試返回結果
從上圖可知返回了自定義信息
四、注意事項
1、如果實現自定義異常處理
- 類上使用
@RestControllerAdvice
註解 - 方法上使用
@ExceptionHandler
來處理特定的異常
2、ResponseEntityExceptionHandler默認處理那些異常
3、使用了ResponseEntityExceptionHandler後,為什麼發生了異常後返回體為空
默認情況下,實現了 ResponseEntityExceptionHandler
這個類後,這個類處理的所有異常的響應結果都是 null
,如果想返回別的值需要我們自己去處理。
五、總結
1、如果我們想處理自定義異常,則可以使用 @RestControllerAdvice
|| @ControllerAdvice
配置@ExceptionHandler
來使用。
2、如果我們實現了ResponseEntityExceptionHandler
來處理異常,那麼默認的異常的響應結果為空,如果想不為空,則需要我們自己處理。
3、默認情況下,標準的Spring MVC異常會通過DefaultHandlerExceptionResolver
來處理。
六、代碼實現
//gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/springboot-exception-handler