之前接手舊後端系統,發現在處理例外的時候有一些 bad smell,例如:
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody UserRequest request) {
try {
User user = userService.create(request);
return ResponseEntity.ok(user);
} catch (IllegalArgumentException e) {
return ResponseEntity.badRequest().build();
} catch (Exception e) {
return ResponseEntity.internalServerError().build();
}
}每個 API 幾乎一樣用一個大 try-cache 裡面做很多事,也有可能 cache 許多不同的 exception,這樣會產生很多重複的程式碼,controller 要做的事情也變得複雜。
藉由這個專案,記錄比較好的做法,例如:
- 自訂符合商業邏輯的例外。
- 使用
@RestControllAdvice集中例外處理流程。
{
"name": "ooxxooxxooxx",
"age": 17
}HTTP 400 Bad Request
{
"summary": "VALIDATION_FAILED",
"detail": "age: Must be at least 18"
}此範例搭配 @RestControllerAdvice 與使用 spring validation 輔助判斷參數是否合乎限制,避免或減少重複的判斷程式碼,而且回應的內容也可以一致。
curl "http://localhost:8080/api/user/12345678"HTTP 404 Not Found
此 API 套用 Null Object Pattern 來表示查無資料,取代用 null 判斷、拋出找不到的例外...等作法。
curl "http://localhost:8080/api/user?id=12345678&name=ooxx"{
"summary": "Violate business rule",
"detail": "違反..."
}此範例搭配 @RestControllerAdvice 攔截自訂 unchecked exception,這樣在 controller 就不用一堆 try-cache。