在 Spring Boot 3 中迁移 HttpStatus 到 HttpStatusCode
1、概览
本文将带你了解如何在 Spring Boot 应用中使用 HttpStatusCode
,重点是 3.3.3 版中引入的最新增强功能。通过这些增强功能,HttpStatusCode
已被纳入 HttpStatus
实现,从而简化了我们处理 HTTP 状态码的方式。
这些改进的主要目的是提供一种更灵活、更可靠的方法来处理标准和自定义 HTTP 状态码,使我们在处理 HTTP 响应时具有更高的灵活性和可扩展性,同时保持向后兼容性。
2、HttpStatus 枚举
在 Spring 3.3.3 之前,HTTP 状态码在 HttpStatus
中表示为枚举。这限制了自定义或非标准 HTTP 状态码的使用,因为枚举是一组固定的预定义值。
尽管 HttpStatus
类尚未被弃用,但一些返回原始 Integer
状态码的枚举和方法(如 getRawStatusCode()
和 rawStatusCode()
)现已被弃用。
使用
@ResponseStatus
注解来提高代码的可读性仍然是我们推荐的方法。
我们可以将 HttpStatus
与 HttpStatusCode
结合使用,以实现更灵活的 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、HttpStatusCode 接口
HttpStatusCode
接口旨在支持 HttpStatus
中预定义状态码之外的自定义状态码。它有 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) 静态方法
本方法为给定的 int
值返回一个 HttpStatusCode
对象。输入参数必须是三位正数,否则会抛出 IllegalArgumentException
异常。
valueOf()
方法将状态码映射到 HttpStatus
中的相应枚举值。如果没有与所提供状态码匹配的现有条目,该方法默认返回 DefaultHttpStatusCode
的实例。
DefaultHttpStatusCode
类实现了 HttpStatusCode
,并直接实现了 value()
方法,该方法返回初始化时使用的原始 Integer
值。这种方法确保了所有 HTTP 状态码,无论是自定义的还是非标准的,都能轻松拿捏:
@GetMapping("/custom-exception")
public ResponseEntity<String> goneStatusCode() {
throw new ResourceGoneException("Resource Gone", HttpStatusCode.valueOf(410));
}
4、在自定义异常中使用 HttpStatusCode
接下来,看看如何在 ExceptionHandler
中使用带有 HttpStatusCode
的自定义异常。我们使用 @ControllerAdvice
注解在所有 Controller 中全局处理异常,并使用 @ExceptionHandler
注解管理自定义异常的实例。
这种方法将异常处理集中在 Spring MVC 应用中,使代码更简洁、更易维护。
4.1、@ControllerAdvice 和 @ExceptionHandler
@ControllerAdvice
处理全局异常,而 @ExceptionHandler
则管理自定义异常实例,以返回包含异常消息和状态码的一致 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、总结
HttpStatus
枚举包含一组有限的标准 HTTP 状态码,在旧版本的 Spring 中可以很好地满足大多数用例的要求。不过,它们在定义自定义状态码时缺乏灵活性。
Spring Boot 3.3.3 引入了 HttpStatusCode
,允许我们定义自定义状态码,从而解决了这一限制。这提供了一种更灵活的方式来处理 HTTP 状态码,并为常用状态码(如 is2xxSuccessful()
和 is3xxRedirection()
)提供了实例方法,最终允许对响应处理进行更细粒度的控制。
Ref:https://www.baeldung.com/spring-boot-httpstatuscode