一、概述
在分布式系统中,服务之间的调用是非常常见的。而服务之间的调用,一般会采用HTTP协议进行通信。在Java语言中,HttpClient和Feign是两个很常见的HTTP客户端库。
HttpClient是Apache软件基金会提供的一个用于HTTP通信的开源Java库。它支持HTTP/1.1和HTTP/2协议,并提供了很多功能强大的特性,如连接池、请求重试、请求拦截器、响应拦截器等等。
Feign是一个声明式的HTTP客户端库,它是由Netflix开源的。Feign的主要特点是可以通过注解的方式定义HTTP请求的接口,并且可以将接口直接映射到具体的实现类上。这样,在编写代码时,我们可以像调用本地方法一样来调用远程服务。
本文将介绍HttpClient和Feign的基本用法、应用场景以及它们之间的区别和联系。
二、HttpClient的基本用法
1. 引入依赖
在使用HttpClient之前,我们需要先引入相关的依赖。在Maven项目中,我们可以在pom.xml文件中添加如下依赖:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
2. 发送GET请求
使用HttpClient发送GET请求非常简单,示例代码如下:
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.io.IOException;
public class HttpClientDemo {
public static void main(String[] args) throws IOException {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("https://www.baidu.com");
CloseableHttpResponse response = httpClient.execute(httpGet);
System.out.println(response.getStatusLine().getStatusCode());
response.close();
httpClient.close();
}
}
上述代码中,我们首先创建了一个CloseableHttpClient对象,然后创建了一个HttpGet对象,设置了请求的URL。接着,我们使用httpClient.execute(httpGet)方法发送了GET请求,并获取到了响应对象。最后,我们可以通过response.getStatusLine().getStatusCode()方法获取到HTTP响应的状态码。
3. 发送POST请求
使用HttpClient发送POST请求也非常简单,示例代码如下:
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.io.IOException;
public class HttpClientDemo {
public static void main(String[] args) throws IOException {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("https://www.baidu.com");
StringEntity stringEntity = new StringEntity("key1=value1&key2=value2");
httpPost.setEntity(stringEntity);
CloseableHttpResponse response = httpClient.execute(httpPost);
System.out.println(response.getStatusLine().getStatusCode());
response.close();
httpClient.close();
}
}
上述代码中,我们首先创建了一个CloseableHttpClient对象,然后创建了一个HttpPost对象,设置了请求的URL。接着,我们创建了一个StringEntity对象,将请求参数设置为字符串格式,并通过httpPost.setEntity(stringEntity)方法将请求参数设置到HttpPost对象中。最后,我们使用httpClient.execute(httpPost)方法发送了POST请求,并获取到了响应对象。
4. 使用连接池
在实际应用中,我们可能需要频繁地发送HTTP请求。这时,使用连接池可以提高HTTP请求的性能。HttpClient提供了连接池的支持,示例代码如下:
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.io.IOException;
public class HttpClientDemo {
public static void main(String[] args) throws IOException {
CloseableHttpClient httpClient = HttpClients.custom()
.setMaxConnTotal(100)
.setMaxConnPerRoute(20)
.build();
HttpGet httpGet = new HttpGet("https://www.baidu.com");
CloseableHttpResponse response = httpClient.execute(httpGet);
System.out.println(response.getStatusLine().getStatusCode());
response.close();
httpClient.close();
}
}
上述代码中,我们使用HttpClients.custom()方法创建了一个HttpClientBuilder对象,然后通过setMaxConnTotal()和setMaxConnPerRoute()方法设置了连接池的最大连接数和每个路由的最大连接数。最后,我们使用build()方法创建了一个CloseableHttpClient对象。
5. 使用请求拦截器和响应拦截器
在实际应用中,我们可能需要对HTTP请求和响应进行一些处理,比如添加请求头、记录日志等等。HttpClient提供了请求拦截器和响应拦截器的支持,示例代码如下:
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import java.io.IOException;
public class HttpClientDemo {
public static void main(String[] args) throws IOException {
CloseableHttpClient httpClient = HttpClients.custom()
.addInterceptorFirst(new HttpRequestInterceptor() {
@Override
public void process(HttpRequest httpRequest, HttpContext httpContext) throws HttpException, IOException {
System.out.println("HttpRequestInterceptor: " + httpRequest);
}
})
.addInterceptorFirst(new HttpResponseInterceptor() {
@Override
public void process(HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException {
System.out.println("HttpResponseInterceptor: " + httpResponse);
}
})
.build();
HttpGet httpGet = new HttpGet("https://www.baidu.com");
CloseableHttpResponse response = httpClient.execute(httpGet);
System.out.println(response.getStatusLine().getStatusCode());
response.close();
httpClient.close();
}
}
上述代码中,我们使用HttpClients.custom()方法创建了一个HttpClientBuilder对象,然后通过addInterceptorFirst()方法添加了一个请求拦截器和一个响应拦截器。在请求拦截器中,我们可以打印出HTTP请求的信息;在响应拦截器中,我们可以打印出HTTP响应的信息。
三、Feign的基本用法
1. 引入依赖
在使用Feign之前,我们需要先引入相关的依赖。在Maven项目中,我们可以在pom.xml文件中添加如下依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
2. 创建接口
在使用Feign时,我们需要先创建一个接口,用于定义HTTP请求的方法。示例代码如下:
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "baidu", url = "https://www.baidu.com")
public interface BaiduFeignClient {
@GetMapping("/")
String index();
@GetMapping("/s")
String search(@RequestParam("wd") String keyword);
}
上述代码中,我们首先通过@FeignClient注解定义了一个Feign客户端,指定了客户端的名称和请求的URL。接着,我们定义了两个HTTP请求的方法,分别是访问百度首页和搜索关键词。在方法上,我们使用@GetMapping注解定义了HTTP请求的方法和路径,并使用@RequestParam注解定义了HTTP请求的参数。
3. 调用接口
在创建了Feign接口后,我们就可以像调用本地方法一样来调用远程服务了。示例代码如下:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
@EnableFeignClients
public class FeignDemo {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(FeignDemo.class, args);
BaiduFeignClient baiduFeignClient = context.getBean(BaiduFeignClient.class);
String index = baiduFeignClient.index();
String search = baiduFeignClient.search("java");
System.out.println(index);
System.out.println(search);
}
}
上述代码中,我们首先通过@EnableFeignClients注解启用了Feign客户端。接着,我们使用context.getBean()方法获取到了BaiduFeignClient接口的实现类,并调用了index()和search()方法。
四、应用场景
1. HttpClient的应用场景
HttpClient适用于以下场景:
- 需要对HTTP请求和响应进行详细的控制和处理;
- 需要使用连接池来提高HTTP请求的性能;
- 需要发送大文件或大量数据的HTTP请求。
2. Feign的应用场景
Feign适用于以下场景:
- 需要快速地创建和使用HTTP请求的接口;
- 需要将HTTP请求的接口直接映射到具体的实现类上;
- 需要在微服务架构中进行服务调用。
五、HttpClient和Feign的区别和联系
1. 区别
- HttpClient是一个通用的HTTP客户端库,可以用于发送各种类型的HTTP请求。而Feign是一个声明式的HTTP客户端库,用于快速地创建和使用HTTP请求的接口。
- HttpClient可以对HTTP请求和响应进行详细的控制和处理,支持连接池、请求重试、请求拦截器、响应拦截器等特性。而Feign的特点是可以将HTTP请求的接口直接映射到具体的实现类上,使得我们可以像调用本地方法一样来调用远程服务。
- HttpClient是一个开源的Java库,由Apache软件基金会提供。而Feign是由Netflix开源的。
2. 联系
- HttpClient和Feign都是用于发送HTTP请求的Java库。
- HttpClient和Feign都支持HTTP/1.1和HTTP/2协议。
六、总结
本文介绍了HttpClient和Feign的基本用法、应用场景以及它们之间的区别和联系。在实际应用中,我们可以根据具体的需求来选择使用HttpClient或Feign。如果需要对HTTP请求和响应进行详细的控制和处理,或者需要发送大文件或大量数据的HTTP请求,可以选择使用HttpClient;如果需要快速地创建和使用HTTP请求的接口,或者需要在微服务架构中进行服务调用,可以选择使用Feign。
公众号请关注"果酱桑", 一起学习,一起进步!