上文中,我们了解到要实现
Feign
客户端,主要是将 Method 方法的参数解析成 Http 请求的请求行、请求行、请求体,然后使用 HttpClient 发送请求。但为了实现这些设想,要解决以下问题:
1. REST 声明式规范(即支持的注解)有以下几种:Feign、JAX-RS 1/2、Spring Web MVC 都需要进行适配。这几种声明式注解的适配接口是 feign.Contract。
2. Http 客户端有 JDK 自带的 HttpURLConnection、Apache HttpComponnets、OkHttp3 、Netty 等,需要适配。这几种客户端的适配接口是 feign.Client。
3. 支持负载均衡与熔断。负载均衡 Ribbon 是对 feign.Client 进行包装。熔断 Hystrix 在 HystrixFeign 中自定义 InvocationHandlerFactory 的实现,创建 HystrixInvocationHandler,对 method.invoke 请求做拦截。
4. 各种编解码的适配,实现接口 feign.codec.Decoder 和 feign.codec.Encoder。
下面一个一个来了解一下这些问题的feign解决方案:
1. REST 声明式规范
REST框架 | 使用场景 | 请求映射注解 | 请求参数 |
---|---|---|---|
JAX-RS( Java API for RESTful Web Services, 参考:使用 JAX-RS 简化 REST 应用开发) | 客户端声明、 服务端声明 | @Path | @PathParam |
Feign | 客户端声明 | @RequestLine | @Param |
Spring Web MVC | 服务端声明 | @ReqeustMapping | @RequestParam |
总结: 这几种规范,其中 Feign
已经适配了 JAX-RS 1/2 和 Feign 自带的注解规范。Spring Cloud Open Feign
进一步适配了 Spring Web MVC 的注解规范。
1.1 Feign(默认): 在客户端声明,注解用@RequestLine,参数用@Param
1)访问接口
//接口中用@RequestLine
public interface GitHub {
// https://api.github.com/repos/OpenFeign/feign/contributors
@RequestLine("GET /repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);
}
2)测试类
public class Test{
//这里用 Feign.builder()
public static void main(String[] args) {
GitHub github = Feign.builder()
.decoder(new GsonDecoder())
.target(GitHub.class, "https://api.github.com");
List<Contributor> contributors = github.contributors("OpenFeign", "feign");
for (Contributor contributor : contributors) {
System.out.println(contributor);
}
}
}
1.2 JAX-RS: 客户端声明、服务端声明 @Path, @PathParam
将上面的列子改成用JAX-RS的实现
1) pom.xml中引入JAX-RS依赖
<!-- Feign对JAXRS的支持 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jaxrs</artifactId>
<version>9.5.0</version>
</dependency>
<!-- JAXRS -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
</dependency>
2) 访问接口类
public interface GitHub2_javax {
@GET
@Path("/repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@PathParam("owner") String owner, @PathParam("repo") String repo);
}
3). 测试类
public class Test {
public static void main(String[] args) {
GitHub2_javax github = Feign.builder()
.decoder(new GsonDecoder())
.options( new Request.Options(1000,3500)) //options方法指定连接超时时长及响应超时时长
// retryer方法主要是指定重试策略
.retryer( new Retryer.Default(5000,5000,3))
// Contract 指明是哪种注解规范
.contract(new JAXRSContract())
// 为构造器配置本地的代理接口,和远程的根目录。代理接口类的每一个接口方法前@RequestLine 声明的值,最终都会加上这个根目录。
.target(GitHub2_javax.class, "https://api.github.com");
List<Contributor> contributors = github.contributors("OpenFeign", "feign");
for (Contributor contributor : contributors) {
System.out.println(contributor);
}
}
}
1.3. Spring Web MVC的例子在一般用在spring cloud整合feign中,这里就不再展示了
2. 多Http客户端支持:
只演示一下OkHttp的用法,其它的客户端插件是一样的
1) 引入maven 依赖:feign-okhttp
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>10.2.0</version>
</dependency>
2)只须修改一下创建代理的代码即可. 其它的都和上面一样.
GitHub2_javax github = Feign.builder()
.client(new OkHttpClient())
.decoder(new GsonDecoder())
.contract(new JAXRSContract())
.target(GitHub2_javax.class, "https://api.github.com");
3. 负载均衡与熔断
3.1 Hystrix: 熔断与降级
1) 引入maven 依赖: feign-hystrix
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-hystrix</artifactId>
<version>8.18.0</version>
</dependency>
2) 只须修改创建代理的代码, 将原来的Feign改为HystrixFeign即可,其它方法都一样。
GitHub github = HystrixFeign.builder()
.target(GitHub.class, "https://myAppProd");
3.2 Ribbon :负载均衡
1) 引入maven 依赖:feign-ribbon
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-ribbon</artifactId>
<version>8.15.1</version>
</dependency>
2) 只须修改创建代理的代码即可。
GitHub github = Feign.builder()
.client(RibbonClient.create())
.target(GitHub.class, "https://myAppProd");
4.编解码器: Gson,Jackson, JAXB, SOAP
4.1 Gson:最常用
1)引入maven 依赖:feign-gson
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
<version>10.4.0</version>
</dependency>
2) 只须修改创建代理的代码即可
public class MyApp {
public static void main(String[] args) {
GitHub github = Feign.builder()
.encoder(new GsonEncoder())
.decoder(new GsonDecoder())
.options(new Request.Options(10000,10000,true))
.target(GitHub.class, "https://api.github.com");
List<Contributor> contributors = github.contributors("OpenFeign", "feign");
for (Contributor contributor : contributors) {
System.out.println(contributor);
}
}
}
4.2 Jackson:
1) 引入maven 依赖: feign-jackson
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId>
<version>11.0</version>
</dependency>
2) 修改源码
GitHub github = Feign.builder()
.encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
.options(new Request.Options(10000,10000,true))
.target(GitHub.class, "https://api.github.com");
参考: https://blog.csdn.net/zhangyingchengqi/article/details/109385205