Feign入门
Feign是Github上的一个开源项目,目的是简化Web Service客户端的开发。在使用Feign时,可以使用注解来修饰接口,被注解修饰的接口具有访问Web Service的能力。这些注解中既包括Feign自带的注解,也支持使用第三方注解。除此之外,Feign还支持插件式的编码器和解码器,使用者可以通过该特性对请求和响应进行不同和的封装和解封。
第一个Feign程序
Feign-Client 端代码
新建一个Maven项目Feign-Client,作为请求发起端,其pom依赖为:
1 | <dependencies> |
然后新建一个接口,命名为HelloClient,添加以下代码:
1 | public interface HelloClient { |
注解@RequestLine表示使用GET方法向/hello发送请求。
接着再新建一个接口,命名为PersonClient,添加以下代码:
1 | public interface PersonClient { |
同样的,注解@RequestLine表示使用GET方法,向链接/person/{personId}发送请求。
其中Person对象的代码如下所示:
1 |
|
最后,编写测试代码,
1 | public class TestClient { |
可以看到,我们使用了Feign创建了HelloClient和PersonClient的实例,接着调用接口定义的方法。Feign就会替我们生成动态代理类,生成的代理类会将请求的信息封装,交给feign.client接口发送请求,而该接口的默认实现类最终会使用java.net.HttpURLConnection来发送HTTP请求。
Feign-Server端代码
接着,创建一个服务端代码,提供/hello和/person/{personId}这两个接口。因为比较简单,就直接贴代码了。
pom文件
1 | <dependencyManagement> |
接口Controller
1 |
|
启动类
1 |
|
运行客户端请求
运行Client的主方法,可以得到如下结果:
实现自定义的编码和解码器
Feign插件式编码器与解码器可以对请求以及结果进行处理。对于一些特殊的要求,可以使用自定义的编码器和解码器。实现自定义的编码器,需要实现Encoder接口的encode方法。
实现自定义encoder
下面是一个自定义编码器的实现
1 | public class MyEncoder implements Encoder { |
实现自定义decoder
实现自定义解码器,需要实现Decoder接口的decode方法。下面是一个自定义编码器的简易实现:
1 |
|
然后,在测试类中添加如下代码:
1 | public class TestClient { |
最后得到运行结果
实现自定义的Feign客户端
Feign使用一个Client接口来发送请求,默认情况下,使用HttpURLConnection连接Http服务。与编码器类似,客户端也采用插件式设计,也就是说,我们可以实现自己的客户端。只要实现Feign的Client接口并实现它的execute方法即可。
下面我们自己实现一个简单的HttpClient客户端
1 | public class MyFeignClient implements Client { |
然后我们在测试类中使用自定义的Feign Client
1 | public static void main(String[] args) { |
可以看到能正常获取结果
使用自定义的注解
通过注解修改的接口方法,可以让接口方法获得访问服务的能力。除了Feign自带的方法外,还可以使用第三方的注解。如果向使用JAXRS贵方的注解,可以使用Feign-jaxrs模块,在Pom文件中加入以下依赖即可:
1 | <dependency> |
在使用注解修饰接口时,可以直接使用@GET、@Path等注解,例如想要使用GET方法调用/hello服务,可以定义以下接口:
1 |
|
以上修饰接口的,实际上等价于@RequestLine(“GET /hello”)。为了让Feign知道这些注解的作用,需要在创建服务客户端时调用contract方法来设置JAXRS注解的解析类:
1 | RSClient rsClient = Feign.builder().contract(new JAXRSContract()).target(RSClient.class, "http://localhost:8080/"); |
设置了JAXRSContract后,Feign就知道如何处理接口中的JAXRS注解了。JAXRSContract继承了BaseContract类,BaseContract类实现了Contract接口,简单来说,一个Contract就相当于一个翻译器,Feign本身并不知道这些第三方注解的含义,而是通过实现一个翻译器(Contract)来告诉Feign,这些注解是做什么的。
下面实现一个自定义的注解,来解释下,是如何使用自定义注解完成必要的功能的。
1 |
|
然后我们将HelloClient的RequestLine注解改为自定义的MyUrl注解
1 | public interface HelloClient { |
然后实现一个自己的翻译器MyContract
1 | public class MyContract extends Contract.BaseContract { |
最后,修改测试类,将调用HelloClient处插入自定义的Contract。
1 | public static void main(String[] args) { |
运行结果:
接口日志
默认情况下,不会记录接口的日志,如果需要很清楚地了解接口的调用情况,可以使用logLevel方法进行配置。
1 | package com.kingwang.feign.client; |
设置日志级别为Level.HEADERS,并将其输出到D盘的log.log文件。
设置接口的日志级别,有以下可选值:
- NONE:默认值,不进行日志记录
- BASIC:记录请求方法、URL、响应状态代码和执行时间
- HEADERS:除了BASIC记录的信息外,还包括请求头和响应头
- FULL:记录全部日志,包括请求头、请求体、请求与响应的元数据