在 Spring Boot 项目中,高效稳定的 HTTP 通信是构建强大应用的关键。本节将在 《探究 Eureka 在 Spring Boot 中的配置注入与统一管理机制(下)——第一节》 的基础上,进一步探讨 Spring Boot 项目中常用的 HTTP 客户端,并介绍它们的特点和应用场景。
一、 常用的HTTP客户端
本文展示的最佳实战均以增删改次(PUT, DELTE, POST, GET)四类方式为主,场景均围绕新能源领域客户信息服务展开。
1. RestTemplate
1.1 简介
RestTemplate 是 Spring 框架提供的用于进行 HTTP 请求的强大工具。它封装了许多常见的 HTTP 操作,使得开发者可以轻松地与 RESTful 服务进行交互。
1.2 特点
- 丰富的请求方法:支持 GET、POST、PUT、DELETE 等多种 HTTP 请求方法,满足不同的业务需求。
- 简洁的 API:提供了简洁直观的 API,易于使用和理解。
- 与 Spring 的其他组件无缝集成,方便在 Spring Boot 项目中进行配置和使用。
1.3 应用场景
- 微服务架构中的服务调用:在微服务架构中,不同的服务之间可以通过 RestTemplate 进行通信。
1.4. 最佳实战
public class RestTemplateDemo{
@Autowired
private RestTemplate restTemplate;
@Value("${url:http://ci.com/customer/}")
private String url;
// 增加或者更新客户信息
public int addOrUpdateCustomerInfo(Customer customer){
HttpHeaders headers = new HttpHeaders();
// 需要token可以加到这里
headers.add("Content-Type", "application/json");
HttpEntity entity = new HttpEntity<>(customer, headers);
// post请求的第一种方式
restTemplate.postForObject(url + "add-or-update-customer-info", entity, String.class);
// post请求的第二种方式
restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
// response自己解析就行,这里统一返回默认值0
return 0;
}
// 查询客户信息
public Customer getCustomerInfo(String customerId){
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
HttpUrl httpUrl = HttpUrl.parse(url + "get-customer-info?customerId=123")
.newBuilder()
.addQueryParameter("customer_id", customerId)
.build();
HttpEntity entity = new HttpEntity<>(headers);
// get请求的第一种方式
Customer customer1 = restTemplate.getForEntity(httpUrl.toString(), String.class, entity);
// get请求的第二种方式
Customer customer2 = restTemplate.exchange(httpUrl.toString(), HttpMethod.GET, entity, String.class);
}
// 删除客户信息
public int deleteCustomerInfo(String customerId){
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
HttpUrl httpUrl = HttpUrl.parse(url + "delete-customer-info?customerId=123")
.newBuilder()
.addQueryParameter("customer_id", customerId)
.build();
HttpEntity entity = new HttpEntity<>(headers);
// delete的第一种方式
restTemplate.delete(httpUrl.toString(), entity);
// delete的第二种方式
restTemplate.exchange(httpUrl.toString(), HttpMethod.DELETE, entity, String.class);
return 0;
}
}
@Data
@Builder
public class Customer{
private String customerId;
private String customerName;
private String customerPhone;
private String sex;
private String idCardNumber;
private List<Product> products;
public static class Product{
public String productId;
public String productName;
// 购买的车的相关信息,按需补充。
}
}
2. OkHttp3
2.1 简介
OkHttp 是一个高效的 HTTP 客户端,被广泛应用于 Android 和 Java 项目中。
2.2 特点
- 高效性能:具有快速的请求响应时间和低内存占用,适合在高并发场景下使用。
- 连接池管理:自动管理连接池,提高连接的复用率,减少连接建立的开销。
- 支持 HTTP/2:可以充分利用 HTTP/2 的特性,提高数据传输效率。
- 拦截器机制:允许开发者在请求和响应的不同阶段进行自定义处理,如添加日志、缓存等功能。
2.3 应用场景
- 移动应用开发:在 Android 应用开发中,OkHttp3 是一个常用的 HTTP 客户端选择。
- 对性能要求较高的项目:如果项目对 HTTP 请求的性能要求较高,OkHttp3 可以提供出色的表现。
2.4 最佳实践
public class OkHttp3Demo{
@Autowired
private OkHttpClient okHttpClient;
@Value("${url:http://ci.com/customer/}")
private String url;
// 增加或者更新客户信息
public int addOrUpdateCustomerInfo(Customer customer){
RequestBody param = RequestBody.create(MediaType.parse("application/json"), JSON.toJSONString(pageParam));
Request request = new Request.Builder().url(url + "add-or-update-customer-info")
.post(param)
.addHeader("Content-Type", "application/json")
.build();
try {
okhttp3.Response response = okHttpClient.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
} catch (IOException e){
e.printStackTrace();
}
return 0;
}
// 查询客户信息
public Customer getCustomerInfo(String customerId){
RequestBody param = RequestBody.create(MediaType.parse("application/json"), JSON.toJSONString(pageParam));
Request request = new Request.Builder().url(url + "get-customer-info?customerId=123"?customerId=123")
.get()
.addHeader("Content-Type", "application/json")
.build();
try {
Response response = okHttpClient.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
// 解析响应体,获取结果
Customer customer = parseJson(response);
return customer;
} catch (IOException e){
e.printStackTrace();
}
return null;
}
// 删除客户信息
public int deleteCustomerInfo(String customerId){
RequestBody param = RequestBody.create(MediaType.parse("application/json"), JSON.toJSONString(pageParam));
Request request = new Request.Builder().url(url + "delete-customer-info?customerId=123"?customerId=123")
.delete()
.addHeader("Content-Type", "application/json")
.build();
try {
Response response = okHttpClient.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
} catch (IOException e){
e.printStackTrace();
}
return 0;
}
}
3. WebClient
3.1 简介
WebClient 是 Spring 5 引入的一个非阻塞式的 HTTP 客户端。它基于 Reactive Streams 规范,提供了一种响应式的编程模型。
3.2 特点
- 非阻塞式编程:采用非阻塞的方式进行 HTTP 请求,能够更好地处理高并发场景。
- 响应式编程模型:支持响应式流,可以方便地进行异步处理和流式数据处理。
- 函数式编程风格:提供了函数式编程的 API,使得代码更加简洁和易于维护。
- 与 Spring WebFlux 的集成:与 Spring WebFlux 框架紧密集成,适用于响应式编程的项目。
3.3 应用场景
- 高并发场景:在需要处理大量并发请求的场景下,WebClient 的非阻塞式特性能够提高系统的性能和响应速度。
- 流式数据处理:对于需要处理流式数据的场景,如实时数据推送、视频流等,WebClient 的响应式编程模型非常适合。
- 响应式项目:如果项目采用了 Spring WebFlux 等响应式框架,WebClient 是一个自然的选择。
3.4 最佳实践
首先,需要引入jar包。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
接下来是代码示例。
public class WebClientDemo{
@Value("${url:http://ci.com/customer/}")
private String url;
@Autowired
private final WebClient webClient = WebClient
.Builder()
.defaultHeader("Content-Type", "application/json").
.baseUrl(url)
.build();
// 增加或者更新客户信息
public int addOrUpdateCustomerInfo(Customer customer){
return webClient.post()
.uri("add-or-update-customer-info")
.bodyValue(pageParam)
.retrieve()
.bodyToMono(Integer.class)
.block();
}
// 查询客户信息
public Customer getCustomerInfo(String customerId){
return webClient.get()
.uri("get-customer-info?customerId=123")
.retrieve()
.bodyToMono(Integer.class)
.block();
}
// 删除客户信息
public int deleteCustomerInfo(String customerId){
return webClient.delete()
.uri("delete-customer-info?customerId=123")
.retrieve()
.bodyToMono(Integer.class)
.block();
}
}
4. HttpClient
4.1 简介
HttpClient 是 Apache HttpComponents 项目的一部分,是一个成熟的 HTTP 客户端库,提供了丰富的功能和灵活的配置选项。它可以独立于 Spring 框架使用,也可以与 Spring 项目进行集成。
4.2 特点
- 强大的功能:支持多种 HTTP 协议版本、连接管理、代理设置等。
- 高度可配置:可以根据不同的需求进行详细的配置,以满足各种复杂的场景。
- 成熟稳定:经过多年的发展和广泛的应用,具有很高的稳定性和可靠性。
4.3 应用场景
- 复杂的 HTTP 通信需求:当需要处理复杂的 HTTP 请求,如自定义请求头、多部分表单提交等,HttpClient 提供了更多的控制和灵活性。
- 与其他系统的集成:如果项目需要与使用 HttpClient 的其他系统进行集成,使用相同的客户端库可以减少兼容性问题。
4.4 最佳实践
public class HttpClientDemo{
private HttpClient httpClient = HttpClients.createDefault();
@Value("${url:http://ci.com/customer/}")
private String url;
// 增加或者更新客户信息
public int addOrUpdateCustomerInfo(Customer customer){
HttpPost postRequest = new HttpPost(url + "add-or-update-customer-info");
StringEntity requestEntity = new StringEntity(JSON.toJSONString(customer), "UTF-8");
postRequest.setEntity(requestEntity);
try {
HttpResponse response = httpClient.execute(postRequest);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new RuntimeException("HTTP请求失败,状态码:" + response.getStatusLine().getStatusCode());
}
HttpEntity entity = response.getEntity();
// 自己解析
} catch (IOException e){
e.printStackTrace();
}
return 0;
}
// 查询客户信息
public Customer getCustomerInfo(String customerId){
HttpGet getRequest = new HttpGet(url + "get-customer-info?customerId=123");
try {
HttpResponse response = httpClient.execute(getRequest);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new RuntimeException("HTTP请求失败,状态码:" + response.getStatusLine().getStatusCode());
}
HttpEntity entity = response.getEntity();
// 自己解析
} catch (IOException e){
e.printStackTrace();
}
return null;
}
// 删除客户信息
public int deleteCustomerInfo(String customerId){
HttpDelete deleteRequest = new HttpGet(url + "get-customer-info?customerId=123");
try {
HttpResponse response = httpClient.execute(deleteRequest);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new RuntimeException("HTTP请求失败,状态码:" + response.getStatusLine().getStatusCode());
}
HttpEntity entity = response.getEntity();
// 自己解析
} catch (IOException e){
e.printStackTrace();
}
return 0;
}
}
二、不同HTTP客户端的比较
1. 易用性比较
- RestTemplate 的 API 相对简单直观,易于上手。对于熟悉 Spring 框架的开发者来说,使用起来非常方便。
- WebClient 的响应式编程模型可能需要一定的学习成本,但一旦掌握,能够提供更加灵活和高效的编程方式。
- OkHttp3 的 API 也比较简洁,但相对 RestTemplate 来说可能需要更多的配置。
- HttpClient 的配置相对复杂,但提供了更多的高级功能,可以满足复杂的需求。
2. 与Spring生态系统的集成
- RestTemplate 是 Spring 框架的一部分,与 Spring 的其他组件集成度非常高。可以方便地与 Spring Security、Spring Data 等进行集成。
- WebClient 也是 Spring 5 引入的响应式编程工具,与 Spring 的响应式生态系统紧密集成。
- OkHttp3 可以通过一些集成库与 Spring 项目进行集成,但集成度相对较低。
- HttpClient 虽然不是 Spring 框架的一部分,但可以通过一些集成库与 Spring 项目进行集成。
笔者公司使用的基本都是RestTemplate和OkHttp3。,所以笔者推荐优先选择RestTemplate和OkHttp3。
三、总结
在 Spring Boot 项目中,选择合适的 HTTP 客户端对于实现高效稳定的 HTTP 通信至关重要。RestTemplate、OkHttp3、WebClient 和 HttpClient 都是常用的 HTTP 客户端,它们各有特点和优势,适用于不同的场景。在实际项目中,开发者可以结合项目的具体需求,选择最适合的 HTTP 客户端。