詳解SpringBoot 處理異常的幾種常見(jiàn)姿勢(shì)
一、使用 @ControllerAdvice 和 @ExceptionHandler 處理全局異常
這是目前很常用的一種方式,非常推薦。測(cè)試代碼中用到了 Junit 5,如果你新建項(xiàng)目驗(yàn)證下面的代碼的話,記得添加上相關(guān)依賴。
1. 新建異常信息實(shí)體類
非必要的類,主要用于包裝異常信息。
src/main/java/com/twuc/webApp/exception/ErrorResponse.java
/** * @author shuang.kou */ public class ErrorResponse { private String message; private String errorTypeName; public ErrorResponse(Exception e) { this(e.getClass().getName(), e.getMessage()); } public ErrorResponse(String errorTypeName, String message) { this.errorTypeName = errorTypeName; this.message = message; } ......省略getter/setter方法 }
2. 自定義異常類型
src/main/java/com/twuc/webApp/exception/ResourceNotFoundException.java
一般我們處理的都是 RuntimeException ,所以如果你需要自定義異常類型的話直接集成這個(gè)類就可以了。
/** * @author shuang.kou * 自定義異常類型 */ public class ResourceNotFoundException extends RuntimeException { private String message; public ResourceNotFoundException() { super(); } public ResourceNotFoundException(String message) { super(message); this.message = message; } @Override public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
3. 新建異常處理類
我們只需要在類上加上@ControllerAdvice注解這個(gè)類就成為了全局異常處理類,當(dāng)然你也可以通過(guò) assignableTypes指定特定的 Controller 類,讓異常處理類只處理特定類拋出的異常。
src/main/java/com/twuc/webApp/exception/GlobalExceptionHandler.java
/** * @author shuang.kou */ @ControllerAdvice(assignableTypes = {ExceptionController.class}) @ResponseBody public class GlobalExceptionHandler { ErrorResponse illegalArgumentResponse = new ErrorResponse(new IllegalArgumentException("參數(shù)錯(cuò)誤!")); ErrorResponse resourseNotFoundResponse = new ErrorResponse(new ResourceNotFoundException("Sorry, the resourse not found!")); @ExceptionHandler(value = Exception.class)// 攔截所有異常, 這里只是為了演示,一般情況下一個(gè)方法特定處理一種異常 public ResponseEntity<ErrorResponse> exceptionHandler(Exception e) { if (e instanceof IllegalArgumentException) { return ResponseEntity.status(400).body(illegalArgumentResponse); } else if (e instanceof ResourceNotFoundException) { return ResponseEntity.status(404).body(resourseNotFoundResponse); } return null; } }
4. controller模擬拋出異常
src/main/java/com/twuc/webApp/web/ExceptionController.java
/** * @author shuang.kou */ @RestController @RequestMapping("/api") public class ExceptionController { @GetMapping("/illegalArgumentException") public void throwException() { throw new IllegalArgumentException(); } @GetMapping("/resourceNotFoundException") public void throwException2() { throw new ResourceNotFoundException(); } }
使用 Get 請(qǐng)求 localhost:8080/api/resourceNotFoundException[1] (curl -i -s -X GET url),服務(wù)端返回的 JSON 數(shù)據(jù)如下:
{ "message": "Sorry, the resourse not found!", "errorTypeName": "com.twuc.webApp.exception.ResourceNotFoundException" }
5. 編寫(xiě)測(cè)試類
MockMvc 由org.springframework.boot.test包提供,實(shí)現(xiàn)了對(duì)Http請(qǐng)求的模擬,一般用于我們測(cè)試 controller 層。
/** * @author shuang.kou */ @AutoConfigureMockMvc @SpringBootTest public class ExceptionTest { @Autowired MockMvc mockMvc; @Test void should_return_400_if_param_not_valid() throws Exception { mockMvc.perform(get("/api/illegalArgumentException")) .andExpect(status().is(400)) .andExpect(jsonPath("$.message").value("參數(shù)錯(cuò)誤!")); } @Test void should_return_404_if_resourse_not_found() throws Exception { mockMvc.perform(get("/api/resourceNotFoundException")) .andExpect(status().is(404)) .andExpect(jsonPath("$.message").value("Sorry, the resourse not found!")); } }
二、 @ExceptionHandler 處理 Controller 級(jí)別的異常
我們剛剛也說(shuō)了使用@ControllerAdvice注解 可以通過(guò) assignableTypes指定特定的類,讓異常處理類只處理特定類拋出的異常。所以這種處理異常的方式,實(shí)際上現(xiàn)在使用的比較少了。
我們把下面這段代碼移到 src/main/java/com/twuc/webApp/exception/GlobalExceptionHandler.java 中就可以了。
@ExceptionHandler(value = Exception.class)// 攔截所有異常 public ResponseEntity<ErrorResponse> exceptionHandler(Exception e) { if (e instanceof IllegalArgumentException) { return ResponseEntity.status(400).body(illegalArgumentResponse); } else if (e instanceof ResourceNotFoundException) { return ResponseEntity.status(404).body(resourseNotFoundResponse); } return null; }
三、 ResponseStatusException
研究 ResponseStatusException 我們先來(lái)看看,通過(guò) ResponseStatus注解簡(jiǎn)單處理異常的方法(將異常映射為狀態(tài)碼)。
src/main/java/com/twuc/webApp/exception/ResourceNotFoundException.java
@ResponseStatus(code = HttpStatus.NOT_FOUND) public class ResourseNotFoundException2 extends RuntimeException { public ResourseNotFoundException2() { } public ResourseNotFoundException2(String message) { super(message); } }
src/main/java/com/twuc/webApp/web/ResponseStatusExceptionController.java
@RestController @RequestMapping("/api") public class ResponseStatusExceptionController { @GetMapping("/resourceNotFoundException2") public void throwException3() { throw new ResourseNotFoundException2("Sorry, the resourse not found!"); } }
使用 Get 請(qǐng)求 localhost:8080/api/resourceNotFoundException2[2] ,服務(wù)端返回的 JSON 數(shù)據(jù)如下:
{ "timestamp": "2019-08-21T07:11:43.744+0000", "status": 404, "error": "Not Found", "message": "Sorry, the resourse not found!", "path": "/api/resourceNotFoundException2" }
這種通過(guò) ResponseStatus注解簡(jiǎn)單處理異常的方法是的好處是比較簡(jiǎn)單,但是一般我們不會(huì)這樣做,通過(guò)ResponseStatusException會(huì)更加方便,可以避免我們額外的異常類。
@GetMapping("/resourceNotFoundException2") public void throwException3() { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Sorry, the resourse not found!", new ResourceNotFoundException()); }
使用 Get 請(qǐng)求 localhost:8080/api/resourceNotFoundException2[3] ,服務(wù)端返回的 JSON 數(shù)據(jù)如下,和使用 ResponseStatus 實(shí)現(xiàn)的效果一樣:
{ "timestamp": "2019-08-21T07:28:12.017+0000", "status": 404, "error": "Not Found", "message": "Sorry, the resourse not found!", "path": "/api/resourceNotFoundException3" }
ResponseStatusException 提供了三個(gè)構(gòu)造方法:
public ResponseStatusException(HttpStatus status) { this(status, null, null); } public ResponseStatusException(HttpStatus status, @Nullable String reason) { this(status, reason, null); } public ResponseStatusException(HttpStatus status, @Nullable String reason, @Nullable Throwable cause) { super(null, cause); Assert.notNull(status, "HttpStatus is required"); this.status = status; this.reason = reason; }
構(gòu)造函數(shù)中的參數(shù)解釋如下:
- status :http status
- reason :response 的消息內(nèi)容
- cause :拋出的異常
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章

synchronized及JUC顯式locks?使用原理解析

JavaWeb?Listener?利用Session統(tǒng)計(jì)在線人數(shù)

Spring Boot 使用 Swagger 構(gòu)建 RestAPI 接口文檔

Java實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接的最詳細(xì)教程分享

Java實(shí)現(xiàn)簡(jiǎn)易計(jì)算器(逆波蘭表達(dá)式)