51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

在 Spring Boot 3 中迁移 HttpStatus 到 HttpStatusCode

1、概览 {#1概览}

本文将带你了解如何在 Spring Boot 应用中使用 HttpStatusCode,重点是 3.3.3 版中引入的最新增强功能。通过这些增强功能,HttpStatusCode 已被纳入 HttpStatus 实现,从而简化了我们处理 HTTP 状态码的方式。

这些改进的主要目的是提供一种更灵活、更可靠的方法来处理标准和自定义 HTTP 状态码,使我们在处理 HTTP 响应时具有更高的灵活性和可扩展性,同时保持向后兼容性。

2、HttpStatus 枚举 {#2httpstatus-枚举}

Spring 3.3.3 之前,HTTP 状态码在 HttpStatus 中表示为枚举。这限制了自定义或非标准 HTTP 状态码的使用,因为枚举是一组固定的预定义值。

尽管 HttpStatus 类尚未被弃用,但一些返回原始 Integer 状态码的枚举和方法(如 getRawStatusCode()rawStatusCode())现已被弃用。

使用 @ResponseStatus 注解来提高代码的可读性仍然是我们推荐的方法

我们可以将 HttpStatusHttpStatusCode 结合使用,以实现更灵活的 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 接口 {#3httpstatuscode-接口}

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) 静态方法 {#31valueofint-静态方法}

本方法为给定的 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 {#4在自定义异常中使用-httpstatuscode}

接下来,看看如何在 ExceptionHandler 中使用带有 HttpStatusCode 的自定义异常。我们使用 @ControllerAdvice 注解在所有 Controller 中全局处理异常,并使用 @ExceptionHandler 注解管理自定义异常的实例。

这种方法将异常处理集中在 Spring MVC 应用中,使代码更简洁、更易维护。

4.1、@ControllerAdvice 和 @ExceptionHandler {#41controlleradvice-和-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、自定义异常 {#42自定义异常}

接下来,让我们定义一个 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、总结 {#5总结}

HttpStatus 枚举包含一组有限的标准 HTTP 状态码,在旧版本的 Spring 中可以很好地满足大多数用例的要求。不过,它们在定义自定义状态码时缺乏灵活性。

Spring Boot 3.3.3 引入了 HttpStatusCode,允许我们定义自定义状态码,从而解决了这一限制。这提供了一种更灵活的方式来处理 HTTP 状态码,并为常用状态码(如 is2xxSuccessful()is3xxRedirection())提供了实例方法,最终允许对响应处理进行更细粒度的控制。


Ref:https://www.baeldung.com/spring-boot-httpstatuscode

赞(1)
未经允许不得转载:工具盒子 » 在 Spring Boot 3 中迁移 HttpStatus 到 HttpStatusCode