1. 概述
本文將探討如何在 Spring Boot 應用程序中使用 <em HttpStatusCode</em>>,重點介紹 3.3.3 版本中引入的最新增強功能。 通過這些增強功能,<em HttpStatusCode> 已被整合到 <em HttpStatus> 實現中,簡化了我們處理 HTTP 狀態碼的方式。
主要目的是提供一種更靈活和可靠的方法來處理標準和自定義 HTTP 狀態碼,從而在保持向後兼容性的前提下,提高我們處理 HTTP 響應的靈活性和可擴展性。
2. <em>HttpStatus</em> 枚舉
在 Spring 3.3.3 之前,HTTP 狀態碼作為枚舉在 <em>HttpStatus</em> 類中表示。 這種方式限制了使用自定義或非標準 HTTP 狀態碼,因為枚舉具有固定的預定義值集。
儘管 <em>HttpStatus</em> 類尚未被廢棄,但返回原始整數狀態碼的某些枚舉和方法,例如 <em>getRawStatusCode()</em> 和 <em>rawStatusCode()</em> 已經被廢棄。 然而,使用 <@ResponseStatus> 註解以提高代碼可讀性仍然是推薦的方法。
我們還可以將 <em>HttpStatus</em> 與 <em>HttpStatusCode</em> 結合使用,以實現更靈活的 HTTP 響應管理:
@GetMapping("/exception")
public ResponseEntity<String> resourceNotFound() {
HttpStatus statusCode = HttpStatus.NOT_FOUND;
if (statusCode.is4xxClientError()) {
return new ResponseEntity<>("Resource not found", HttpStatusCode.valueOf(404));
}
return new ResponseEntity<>("Resource found", HttpStatusCode.valueOf(200));
}
3. <em>HttpStatusCode</em> 接口
<em>HttpStatusCode</em> 接口 的設計是為了支持超出預定義狀態碼的自定義狀態碼,即超越 <em>HttpStatus</em> 中的預定義狀態碼。它包含 8 個實例方法:
- is1xxInformational()
- is2xxSuccessful()
- is3xxRedirection()
- is4xxClientError()
- is5xxServerError()
- isError()
- isSameCodeAs(HttpStatusCode other)
- value()
這些方法不僅增加了處理不同 HTTP 狀態碼的靈活性,也簡化了檢查響應類別,從而提高了狀態碼管理的清晰度和效率。
@GetMapping("/resource")
public ResponseEntity successStatusCode() {
HttpStatusCode statusCode = HttpStatusCode.valueOf(200);
if (statusCode.is2xxSuccessful()) {
return new ResponseEntity("Success", statusCode);
}
return new ResponseEntity("Moved Permanently", HttpStatusCode.valueOf(301));
}
3.1. 靜態方法 valueOf(int)</h3
此方法返回給定 int 值對應的 HttpStatusCode 對象。 輸入參數必須是一個 3 位正數,否則將拋出 IllegalArgumentException 。
valueOf() 將狀態碼映射到 HttpStatus 中的相應枚舉值。如果未找到匹配提供的狀態碼的現有條目,則該方法默認返回一個 DefaultHttpStatusCode 實例。
DefaultHttpStatusCode 類實現了 HttpStatusCode 接口,並提供了一個簡單的 value() 方法的實現,該方法返回用於初始化其自身的原始整數值。 這種方法確保所有 HTTP 狀態碼,無論是否自定義或非標準,都易於使用:
@GetMapping("/custom-exception")
public ResponseEntity<String> goneStatusCode() {
throw new ResourceGoneException("Resource Gone", HttpStatusCode.valueOf(410));
}4. 使用 HttpStatusCode 在自定義異常中
接下來,讓我們看看如何在自定義異常中使用 HttpStatusCode 在 ExceptionHandler 中。我們將使用 @ControllerAdvice 註解在所有控制器中全局處理異常,以及 @ExceptionHandler 註解來管理自定義異常的實例。
這種方法集中了 Spring MVC 應用程序中的錯誤處理,使代碼更簡潔、更易於維護。
4.1. <em @ControllerAdvice</em> 和 <em @ExceptionHandler</em>
<em @ControllerAdvice</em>> 處理全局異常,而 <em @ExceptionHandler</em>> 則管理自定義異常實例,以便返回一致的 HTTP 響應,其中包含異常消息和狀態碼。
讓我們看看如何在實踐中同時使用這兩個註解:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(CustomException.class)
public ResponseEntity<String> handleGoneException(CustomException e) {
return new ResponseEntity<>(e.getMessage(), e.getStatusCode());
}
}4.2. 自定義異常
接下來,我們定義一個名為 CustomException 的類,該類繼承自 RuntimeException,幷包含一個 HttpStatusCode 字段,從而可以提供自定義消息和 HTTP 狀態碼,實現更精確的錯誤處理:
public class CustomException extends RuntimeException {
private final HttpStatusCode statusCode;
public CustomException(String message, HttpStatusCode statusCode) {
super(message);
this.statusCode = statusCode;
}
public HttpStatusCode getStatusCode() {
return statusCode;
}
}5. 結論
<em>HttpStatus</em> 枚舉包含了一組有限的標準 HTTP 狀態碼,在舊版本的 Spring 中,這些狀態碼對於大多數用例都表現良好。然而,它們缺乏定義自定義狀態碼的靈活性。
Spring Boot 3.3.3 引入了 <em>HttpStatusCode</em>,解決了這一限制,允許我們定義自定義狀態碼。這提供了一種更靈活的方式來處理 HTTP 狀態碼,並提供了諸如 <em>is2xxSuccessful()</em> 和 <em>is3xxRedirection()</em> 等實例方法,從而最終實現了對響應處理的更精細控制。