1. 什么是Feign
概念
Feign是—个声明式、模板化的HTTP客户端,GitHub源码地址。
在HTTP协议中,发送请求的一方就是HTTP 客户端,在JAVA 中,有很多HTTP 客户端框架。
实际Feign 是为了简化HTTP 客户端开发,实际通信部分还是调用了其他客户端框架。
工作原理
Feign 的工作原理是将注解处理成模板化的请求。
核心思想
Feign是声明式服务调用组件,其核心就是:像调用本地方法一样调用远程方法,无感知远程HTTP请求。
它解决了让开发者调用远程接口就跟调用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。无需关注与远程的交互细节,更无需关注分布式环境开发。
Java 版本兼容性
Feign 10.x 及以上版本基于 Java 8 构建,应该适用于 Java 9、10 和 11。对于需要兼容 JDK 6 的用户,请使用 Feign 9.x。
功能
这是一张包含 feign 提供的当前关键功能的图:
1. Clients
Clients 包含了Feign支持的HTTP 客户端:
- java.net.URL:JDK 提供的网络编程工具包
- Apache HTTP:Apache 提供的HTTP Client包
- Apache HC5:Apache 提供的HTTP Client 5.0 版本包
- Google HTTP:Google 提供的Http 客户端工具包
- Java 11 Http2:JDK 11 提供的对HTTP2 的支持工具包
- OK Http : 开源的OkHttp 框架
- Ribbon:基于HTTP和TCP的客户端负载均衡工具,基于Netflix Ribbon实现
2. async clients
Feign 还支持异步的HTTP 客户端:
3. contracts
contracts 部分,包含了Feign 遵守的一些协议规范。
4. encoders/decoders
encoders/decoders
是编码解码相关支持,Feign 在请求之前会进行编码操作,获取响应的时候会进行解码,之所以要进行编解码,是因为发送请求可能是对象,需要编码成服务端能解析的数据格式,比如Json。
Feign 支持常用的Jackson、Gson 及其他JAVA Json工具进行编解码。
5. metrics
metrics
模块,是对Dropwizard 、Micrometer 度量检测工具的支持。
6. extras
extras
额外的其他功能,是对熔断器(Hystrix)、日志(SLF4J)等工具的支持。
2. 常用HTTP客户端案例演示
HttpURLConnection
HttpURLConnection
是在JDK的java.net
包中提供的用于HTTP协议访问的基本功能的类,但是由于使用步骤比较复杂,灵活性不够,所以一般很少直接用。
比如可以通过以下示例发送一个请求并获取响应信息。
// 创建URL
URL url = new URL("https://www.baidu.com");
// 创建连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置请求方法
connection.setRequestMethod("GET");
// 设置连接超时时间
connection.setConnectTimeout(5 * 1000);
// 连接
connection.connect();
// 获取响应的流并专为字符串输出
InputStream inputStream = connection.getInputStream();
byte[] data = new byte[1024];
StringBuilder sb = new StringBuilder();
int length = 0;
while ((length = inputStream.read(data)) != -1) {
String s = new String(data, Charset.forName("utf-8"));
sb.append(s);
}
String message = sb.toString();
System.out.println(message);
// 关闭
inputStream.close();
connection.disconnect();
HttpURLConnection
是基于HTTP协议的,其底层通过socket通信实现。其connect()
方法,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求,实际上直到其getInputStream()
方法执行时才正式发送出去。
HttpClient
尽管java.net
包提供了通过 HTTP 访问资源的基本功能,但它并没有提供许多应用程序所需的灵活性或全部功能。
HttpClient
是Apache Jakarta Common
下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。像很多开源框架通信的底层都是用的HttpClient。
在示例中可以看到,只需要几行代码就可以实现请求了。
// 创建 Http Client
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
// 创建Get请求
HttpGet httpGet = new HttpGet("https://www.baidu.com");
// 执行请求
try (CloseableHttpResponse response = httpclient.execute(httpGet)) {
// 获取结果集
HttpEntity entity1 = response.getEntity();
InputStream content = entity1.getContent();
byte[] buff = new byte[1024];
StringBuilder sb1 = new StringBuilder();
int length1 = 0;
while ((length1 = content.read(buff)) != -1) {
String s = new String(buff, StandardCharsets.UTF_8);
sb1.append(s);
}
String message1 = sb1.toString();
System.out.println(message1);
}
}
注意,最新版为5.X,不要引错依赖包了。
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.1.1</version>
</dependency>
OkHttp
OkHttp
不仅支持Java,还支持Android ,虽然资历没有HttpClient老,但是性能更加卓越,设计更加优秀。
示例如下:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://www.baidu.com")
.get()
.build();
try (Response response = client.newCall(request).execute()) {
String string = response.body().string();
System.out.println(string);
}
Feign
Feign 最初是由Netfilx (网飞) 公司开源的,最初叫 Netfilx Feign ,2016年改名为 Open Feign,所以我们在使用的时候需要注意要使用Open Feign。
接下来使用一个简单案例,看下如何使用Feign 来发送HTTP 请求,和微服务整合会后续再详细介绍。
首先进行环境搭建,为了节约时间,可以参考上面的搭建Spring Cloud 文档。
1. 引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
可以看到,这个版本的Feign 是10.12 。
2. 编写Feign 接口
Feign 是声明式+模板式的,其原理是通过注解来处理模式化的请求,所以需要定义一个接口,使用注解声明HTTP 请求所需要的请求方式、参数、返回值等内容。
@RequestLine
注解,声明了请求方式和请求路径,关于注解的具体使用方式,后续再介绍
public interface TestFeignClient {
@RequestLine("GET /aa")
String test();
}
3. 发送请求
使用Feign 的构造者模式,创建一个客户端,其会根据接口采用JDK动态代理生成,然后通过客户端发送请求。
public static void main(String[] args) {
TestFeignClient feignClient = Feign.builder().target(TestFeignClient.class, "https://baike.baidu.com/");
String test = feignClient.test();
System.out.println(test);
}
最后获取到了该请求的响应数据。