1、简介 {#1简介}
Enum
(枚举)提供了一种在 Java 编程语言中定义一组命名常量的强大方法。这些常量可用于表示相关值的固定集合,例如 HTTP 状态码。总所周知,互联网上的所有 Web 服务器都会响应 HTTP 状态码作为标准响应码。
本文将带你了解如何创建一个包含所有 HTTP 状态码的 Java 枚举。
2、了解 HTTP 状态码 {#2了解-http-状态码}
HTTP 状态码在 Wweb 通信中起着至关重要的作用,它能告知客户端其请求的结果。这些代码分为五类,每一类在 HTTP 协议中都有特定的功能。
3、HTTP 状态码使用枚举的好处 {#3http-状态码使用枚举的好处}
在 Java 中枚举 HTTP 状态码有几个优点,包括:
- 类型安全:使用
Enum
枚举可确保类型安全,使代码更具可读性和可维护性 - 分组常量:
Enum
枚举将相关常量组合在一起,以清晰和结构化的方式处理固定值集合 - 避免硬编码:将 HTTP 状态码定义为枚举,有助于防止硬编码字符串或整数造成的错误
- 增强清晰度和可维护性:这种方法通过增强清晰度、减少错误和提高代码的可维护性,促进软件开发的最佳实践
4、基本做法 {#4基本做法}
为了在 Java 应用中有效管理 HTTP 状态码,我们可以定义一个枚举来封装所有标准 HTTP 状态码及其描述。
这种方法可以让我们充分利用枚举类型安全和代码清晰的优势。
定义 HttpStatus
枚举:
public enum HttpStatus {
CONTINUE(100, "Continue"),
SWITCHING_PROTOCOLS(101, "Switching Protocols"),
OK(200, "OK"),
CREATED(201, "Created"),
ACCEPTED(202, "Accepted"),
MULTIPLE_CHOICES(300, "Multiple Choices"),
MOVED_PERMANENTLY(301, "Moved Permanently"),
FOUND(302, "Found"),
BAD_REQUEST(400, "Bad Request"),
UNAUTHORIZED(401, "Unauthorized"),
FORBIDDEN(403, "Forbidden"),
NOT_FOUND(404, "Not Found"),
INTERNAL_SERVER_ERROR(500, "Internal Server Error"),
NOT_IMPLEMENTED(501, "Not Implemented"),
BAD_GATEWAY(502, "Bad Gateway"),
UNKNOWN(-1, "Unknown Status");
private final int code;
private final String description;
HttpStatus(int code, String description) {
this.code = code;
this.description = description;
}
public static HttpStatus getStatusFromCode(int code) {
for (HttpStatus status : HttpStatus.values()) {
if (status.getCode() == code) {
return status;
}
}
return UNKNOWN;
}
public int getCode() {
return code;
}
public String getDescription() {
return description;
}
}
该枚举中的每个常量都与一个 int
code 和一个字符串描述相关联,构造函数会初始化这些值。此外,我们还提供了 getter 方法来检索这些值。
创建单元测试,测试 HttpStatus
枚举类:
@Test
public void givenStatusCode_whenGetCode_thenCorrectCode() {
assertEquals(100, HttpStatus.CONTINUE.getCode());
assertEquals(200, HttpStatus.OK.getCode());
assertEquals(300, HttpStatus.MULTIPLE_CHOICES.getCode());
assertEquals(400, HttpStatus.BAD_REQUEST.getCode());
assertEquals(500, HttpStatus.INTERNAL_SERVER_ERROR.getCode());
}
@Test
public void givenStatusCode_whenGetDescription_thenCorrectDescription() {
assertEquals("Continue", HttpStatus.CONTINUE.getDescription());
assertEquals("OK", HttpStatus.OK.getDescription());
assertEquals("Multiple Choices", HttpStatus.MULTIPLE_CHOICES.getDescription());
assertEquals("Bad Request", HttpStatus.BAD_REQUEST.getDescription());
assertEquals("Internal Server Error", HttpStatus.INTERNAL_SERVER_ERROR.getDescription());
}
如上,验证了 getCode()
和 getDescription()
方法是否能返回各种 HTTP 状态码的正确值。第一个测试方法检查 getCode()
方法是否为每个枚举常量返回正确的 int
状态码。同样,第二个测试方法确保 getDescription()
方法返回适当的字符串描述。
5、使用 Apache HttpComponents {#5使用-apache-httpcomponents}
Apache HttpComponents 是一个用于 HTTP 通信的流行库。要在 Maven 中使用它,需要在 pom.xml
中加入以下依赖:
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3.1</version>
</dependency>
你可以在 Maven Central 上找到有关该依赖的更多详细信息。
我们可以使用 HttpStatus
枚举来处理 HTTP 响应:
@Test
public void givenHttpRequest_whenUsingApacheHttpComponents_thenCorrectStatusDescription() throws IOException {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet("http://example.com");
try (CloseableHttpResponse response = httpClient.execute(request)) {
String reasonPhrase = response.getStatusLine().getReasonPhrase();
assertEquals("OK", reasonPhrase);
}
}
如上,首先使用 createDefault()
方法创建一个 CloseableHttpClient
实例。此外,该客户端还负责发出 HTTP 请求。然后,使用 new HttpGet("http://example.com")
向 http://example.com
发送 HTTP GET 请求。使用 execute()
方法执行请求后,我们会收到一个 CloseableHttpResponse
对象。
我们使用 response.getStatusLine().getStatusCode()
从响应中提取状态码。然后,使用 HttpStatusUtil.getStatusDescription()
获取与状态码相关的状态描述。
最后,使用 assertEquals()
来确保描述与预期值相匹配,从而验证状态码处理是否准确。
6、使用 RestTemplate {#6使用-resttemplate}
Spring 的 RestTemplate
也能受益于 HttpStatus
枚举,用于处理 HTTP 响应。
首先在 pom.xml
中加入以下依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>6.1.11</version>
</dependency>
你可以在 Maven Central 上找到有关该依赖的更多详细信息。
来看看如何使用一个简单的实现来利用这种方法:
@Test
public void givenHttpRequest_whenUsingSpringRestTemplate_thenCorrectStatusDescription() {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.getForEntity("http://example.com", String.class);
int statusCode = response.getStatusCode().value();
String statusDescription = HttpStatus.getStatusFromCode(statusCode).getDescription();
assertEquals("OK", statusDescription);
}
如上,我们创建了一个 RestTemplate
实例来执行 HTTP GET 请求。获取响应实体对象后,我们使用 response.getStatusCode().value()
提取状态码。然后,我们将此状态码传递给 HttpStatus.getStatusFromCode.getDescription()
,以获取相应的状态描述。
7、使用 OkHttp 库 {#7使用-okhttp-库}
OkHttp 是 Java 中另一个广泛使用的 HTTP 客户端库。
在 pom.xml
中添加以下依赖:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
你可以在 Maven Central 上找到有关该依赖关系的更多详细信息。
现在,将 HttpStatus
枚举与 OkHttp
集成,以处理响应:
@Test
public void givenHttpRequest_whenUsingOkHttp_thenCorrectStatusDescription() throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://example.com")
.build();
try (Response response = client.newCall(request).execute()) {
int statusCode = response.code();
String statusDescription = HttpStatus.getStatusFromCode(statusCode).getDescription();
assertEquals("OK", statusDescription);
}
}
在这个测试中,我们初始化了一个 OkHttpClient
实例,并使用 Request.Builder()
创建了一个 HTTP GET 请求。然后,我们使用 client.newCall(request).execute()
方法执行请求并获取响应对象。我们使用 response.code()
方法提取状态码,并将其传递给 HttpStatus.getStatusFromCode.getDescription()
方法,以获取状态描述。
8、总结 {#8总结}
本文介绍了如何使用 Java 枚举来表示 HTTP 状态码,从而提高代码的可读性、可维护性和类型安全性。
无论选择简单的枚举定义,还是将其与 Apache HttpComponents、Spring RestTemplate
或 OkHttp 等各种 Java 库一起使用,枚举都足够强大,可以在 Java 中处理固定的相关常量集。
Ref:https://www.baeldung.com/java-enum-http-status