# Java Spring Boot|用 @ExceptionHandler 進行全局例外處理 ## 動機 在 Spring Boot 中,例外可能遍佈整個專案,在沒有全域處理的情況下,開發者必須在 Service 層與 Controller 層之間建立一套複雜的管理機制,例如 controller 可能如下: ```java @GetMapping("/{id}") public ResponseEntity<> get(@PathVariable int id) { try { User user = service.find(id); return ResponseEntity.ok(user); } catch (BusinessException e) { return ResponseEntity.status(HttpStatus.BAD_REQUEST) .body("Business error: " + e.getMessage()); } catch (NotExistError e) { return ResponseEntity.status(HttpStatus.NOT_FOUND) .body("Data not exist."); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("An unexpected error occurred."); } } ``` 上面使用 try-catch 的方法在 controller 層當中進行判斷,會造成代碼冗長以及管理和維護困難,因此使用全域異常處理 (Global Exception Handling) 來管理例外處理,可以讓專案結構更加整潔易讀。 ## 核心概念 利用 Java 的 RuntimeException 特性與 Spring 的全域攔截,我們可以達成: - Service 層:發現錯誤直接丟出,例外會穿透所有中間層級,調用此 service 的所有中間層級都不需要寫任何接收代碼或在方法宣告 throws。 - Controller 層:專注於回傳正確的資料。 ## 實例 首先建立一個全局處理類別; ```java @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(BusinessException.class) public ResponseEntity<String> handleBusiness(BusinessException e) { return ResponseEntity.status(HttpStatus.BAD_REQUEST) .body(e.getMessage()); } @ExceptionHandler(NotExistError.class) public ResponseEntity<String> handleNotFound(NotExistError e) { return ResponseEntity.status(HttpStatus.NOT_FOUND) .body("Data not exist."); } @ExceptionHandler(Exception.class) public ResponseEntity<String> handleGeneral(Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("An unexpected error occurred."); } } ``` 假設 service 層有以下的例外: ```java public User find(int id) { User user = repository.findById(id); if (user == null) throw new NotExistError(); if (user.isLocked()) throw new BusinessException("User account is locked."); return user; } ``` 有了全局例外處理器,就算 service 層有丟出例外,controller 也不需要進行處理。這些例外在 service 被拋出之後,會直接被全局例外處理器接住。 更新後的 controller 可以變得非常簡潔: ```java @GetMapping("/{id}") public ResponseEntity<User> get(@PathVariable int id) { User user = service.find(id); return ResponseEntity.ok(user); } ```
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.