# 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
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up