Feign简介
Feign是一种负载均衡的HTTP客户端, 使用Feign调用API就像调用本地方法一样。
GitHub地址:https://github.com/OpenFeign/feign
Feign使用
1、 引入依赖
至少需要引入核心依赖和一种json或者xml的一种解析工具
Feign将方法签名中方法参数对象序列化为请求参数放到HTTP请求中的过程,是由编码器(Encoder)完成的。同理,将HTTP响应数据反序列化为java对象是由解码器(Decoder)完成的。
json解析工具支持:feign-gson、feign-jackson
xml解析工具支持:feign-sax、feign-jaxb、feign-jaxrs
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-core</artifactId>
<version>8.18.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-jackson</artifactId>
<version>8.18.0</version>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-slf4j</artifactId>
<version>8.18.0</version>
</dependency>
2、 定义Api的接口
定义一个实体,用于将api的结果封装到对象中
public class Contributor {
private String login;
private int contributions;
// Getter&Setter
}
定义一个Api接口,接口中声明每个api对应的请求方式、地址、参数、请求头等信息
import feign.*;
import java.util.List;
import java.util.Map;
// 给BaseApi中的所有方法设置Accept请求头
@Headers("Accept: application/json")
public interface ApiService {
// 查看某个用户下的某个仓库的所有贡献者
@RequestLine("GET /repos/{owner}/{repo}/contributors")
@Headers("Content-Type: application/json") // 单独给put方法设置Content-Type请求头
public List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);
@RequestLine("GET /search/issues")
public Map<String, Object> searchIssues(@QueryMap Map<String, Object> queryMap);
}
定义一个拦截器,用于拦截所有的请求
import feign.RequestInterceptor;
import feign.RequestTemplate;
public class ApiRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
System.out.println("拦截请求:" + requestTemplate.method() + " " + requestTemplate.url());
}
}
3、FeignTest
import feign.Feign;
import feign.Request;
import feign.Retryer;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import feign.okhttp.OkHttpClient;
import feign.slf4j.Slf4jLogger;
import org.junit.Assert;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FeignTest extends SpringTestCase {
@Test
public void testJsonApi(){
// 编码器、解码器: 用于解析响应的内容
Encoder encoder = new JacksonEncoder();
Decoder decoder = new JacksonDecoder();
ApiService apiService = Feign.builder()
.logger(new Slf4jLogger())
.encoder(encoder)
.decoder(decoder)
.requestInterceptor(new ApiRequestInterceptor())
.options(new Request.Options(1000, 3500)) // 设置连接超时时长及响应超时时长
.retryer(new Retryer.Default(5000, 5000, 3)) // 重试策略
.target(ApiService.class, "https://api.github.com"); // 绑定接口和地址
// 其实就是使用Get方法调用https://api.github.com/repos/OpenFeign/feign/contributors
// 可以通过https://api.github.com/ 查看github对外的接口
List<Contributor> contributors = apiService.contributors("OpenFeign", "feign");
Assert.assertNotNull(contributors);
}
// 动态查询参数 queryMap
@Test
public void testDynamicQueryParameters(){
ApiService apiService = Feign.builder()
.logger(new Slf4jLogger())
.encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
.requestInterceptor(new ApiRequestInterceptor())
.target(ApiService.class, "https://api.github.com");
Map<String, Object> queryMap = new HashMap<String, Object>();
queryMap.put("q", "FeignException");
queryMap.put("page", 1);
queryMap.put("per_page", 10);
Map<String, Object> responseMap = apiService.searchIssues(queryMap);
System.out.println(responseMap.size());
}
@Test
public void testOkHttp(){
ApiService apiService = Feign.builder().decoder(new JacksonDecoder()).client(new OkHttpClient()).target(ApiService.class, "https://api.github.com");
List<Contributor> contributors = apiService.contributors("OpenFeign", "feign");
Assert.assertNotNull(contributors);
}
}
Feign在默认情况下使用的是JDK原生的URLConnection发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection 。我们可以用Apache的HTTP Client或者使用OkHttpClient替换Feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力
OkHttpClient 使用 OkHttp 来发送 Feign 的请求,OkHttp 支持 SPDY (SPDY是Google开发的基于TCP的传输层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验),
并有更好的控制http请求。
feign与OkHttp集成
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>8.18.0</version>
</dependency>
GitHubService gitHubService = Feign.builder().decoder(new JacksonDecoder()).client(new OkHttpClient()).target(GitHubService.class, "https://api.github.com");
feign与apache httpclient集成
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>8.18.0</version>
</dependency>
@Test
public void testApacheHttpClient(){
ApiService apiService = Feign.builder().decoder(new JacksonDecoder()).client(new ApacheHttpClient()).target(ApiService.class, "https://api.github.com");
List<Contributor> contributors = apiService.contributors("OpenFeign", "feign");
Assert.assertNotNull(contributors);
}
Feign还可以与Ribbon、Hystrix集成
RibbonClient 重写了 Feign 客户端的对URL的处理,其添加了 智能路由以及一些其他由Ribbon提供的弹性功能。
HystrixFeign 配置了 Hystrix 提供的熔断机制。