Feign介绍
来源:互联网 发布:帝国cms表单反馈邮箱 编辑:程序博客网 时间:2024/05/18 15:50
引言
本文主要介绍Feign是什么,它能给我们带来什么帮助,并简要介绍Feign的设计风格及其各个组件。
本文主要参考Feign的项目主页:https://github.com/Netflix/feign。
Feign是什么
Feign是简化Java HTTP客户端开发的工具(java-to-httpclient-binder),它的灵感来自于Retrofit、JAXRS-2.0和WebSocket。Feign的初衷是降低统一绑定Denominator到HTTP API的复杂度,不区分是否为restful。
为什么使用Feign
开发人员使用Jersey和CXF等工具可以方便地编写java client,从而提供REST或SOAP服务;开发人员也可以基于Apache HC等http传输工具包编写自己的java http client;而Feign的关注点在于简化开发人员使用工具包的复杂度,以最少的代码编写代码从而提供java http客服端。通过定制解码器和异常处理,开发人员可以任意编写文本化的HTTP API。
Feign的工作机制
Feign通过处理注解生成request,从而实现简化HTTP API开发的目的,即开发人员可以使用注解的方式定制request api模板,在发送http request请求之前,feign通过处理注解的方式替换掉request模板中的参数,这种实现方式显得更为直接、可理解。
举个例子,github有个api,我们可以根据owner和repo两个参数,获取所有代码贡献者的贡献次数,代码如下:
可定制化
Feign提供多个组件可供定制化,如拦截器、编码/解码器等,例如,开发人员可以使用Feign的构建器(Feign.builder())构造一个API接口,我们可以使用该构建器定制化我们所需要的组件,例如我们通过decoder()函数传入我们自己的解码器(AccountDecoder),代码如下:
多接口
Feign能够生成多个接口,这些接口组成Target<T>对象(默认为HardCodedTarget<T>),它使得request在执行之前能进行接口动态发现和request的预处理。例如,开发人员可能想要给同一个url下的每个request添加认证token等信息,因此,我们可以实现自己的Target,并加上认证token,例子如下:(其中,CloudIdentityTarget可以包括多个接口)
多组件支持
我们打开Feign.class的源码即可找到其所包括的各个组件,有RequestInterceptor、Logger、Contract、Client、Retryer、Encoder、Decoder、ErrorDecoder、Options以及InvocationHandlerFactory。
RequestInterceptor
在request发送之前,我们可以通过配置RequestInterceptor对request进行预处理。举个例子,若我们只是将request进行转发,我们需要对每个request更改头部信息“X-Forwarded-For”,我们可以这么做:
另一个常见的用法就是进行BA认证,我们可以用Feign内置的BasicAuthRequestInterceptor,如下:
在Feign内部将RequestInterceptor存在ArrayList中,但是RequestInterceptor的javadoc里说明了不保证多个RequestInterceptor的执行顺序。
Logging
通过配置Logger,我们可以记录request的相关信息。在Feign中,我们可以设置Logger和LogLevel两个值,例子如下:
Feign内置三个Logger,分别是JavaLogger、ErrorLogger和NoOpLogger,默认为NoOpLogger。JavaLogger内部使用jul打印request日志;ErrorLogger则简单地通过“System.err.printf”打印信息;NoOpLogger不做任何操作。Feign为我们提供四种Log Level:NONE、BASIC、HEADERS和FULL,NONE为不打印,FULL为打印headers、body和metadata,BASIC打印request method和url或response状态码和headers,HEADERS打印request或response的基本信息。
Feign还实现了Slf4jLogger,我们需要引入feign-slf4j和slf4j等相关依赖包,即可使用slf4j打印request和response日志。
Contract
顾名思义,Contract组件就是用于检查request相关的约定,在Contract内部提供了抽象类BaseContract(模板方法),它主要检查Target的相关信息及其类注解、方法注解和参数注解等,在Contract提供了默认的Contract,其实现了BaseContract。
举个例子,我们创建一个接口(例如取名为GithubAPI),即代表一个request对象,在feign内部即为Target<T>,T即为该接口类型;该接口的每个方法,即对应一个request api;而Contract的作用则是检查该Target相关内容:
- 检查targetType(即GithubAPI)的泛型参数;
- 检查targetType的接口数量以及接口深度;
- 检查GithubAPI的类注解,如@Headers;
- 检查GithubAPI的方法注解,如@RequestLine、@Body、@Headers等;
- 检查GithubAPI的参数注解,如@Param;
Contract除了对GithubAPI进行验证之外,最后还会将其每个方法转化为MethodMetadata对象,形成接口列表,即ArrayList<MethodMetadata>。
由此可知,Feign提供给我们的高级用法,即我们可以通过接口继承的方式实现我们的Request API对象。例如,我们可能有多个资源对象都有共同的操作API接口,代码如下:
BaseApi提供了统一的API接口,并通过参数化使得我们可以应用到不同的资源类型,如Foo和Bar。
Feign的子工程feign-jaxrs给我们提供了JAXRSContract,,它继承自Contract.BaseContract。JAX-RS简单说就是通过注解的方式将Java POJO等封装为web资源类,而Feign的子项目JAXRSContract则是根据JAX-RS规范 V1.1进行实现,目前支持一些注解可以方便的编写restful api,详见JAXRSContract主页。
Client
Client组件应该是最重要的组件之一了,因为Feign最终发送request请求以及接收response响应,都是由Client组件完成的,它们都需要实现Client接口。除了默认的Client实现(Client.Default),Feign还通过子项目(feign-httpclient、feign-okhttp、feign-ribbon)提供多种Client实现,它们都各自集成市面上比较流行的Http Client组件,如Apache HttpClient、Okhttp、Ribbon等,且其默认的Client实现为HttpURLConnection。
Retryer
Feign通过Retryer组件向我们提供重试机制。对于每次Request的执行,Retryer都会调用自身的clone()拷贝一份Retryer,并且在抛出RetryableException异常时进行处理,即retryer.continueOrPropagate(e)。若Retryer认为不应该重试,则将RetryableException往外抛。
Feign提供默认的Retryer实现,其构造函数使得我们可以传入period、maxPeriod和maxAttempts三个参数进行配置,默认的period为100ms,maxPeriod为1000ms,maxAttempts为5次。
Encoder和Decoder
Encoder从名字即可知道它是在request执行前进行encode操作,而Decoder则是在收到response时进行decode操作。在Feign中,除了Encoder和Decoder内部提供的默认实现,其还有feign-gson、feign-jackson、feign-jaxb、feign-jackson-jaxb和feign-sax等子工程分别提供了其对应的Encoder和Decoder。
举个例子,我们可能需要发送一个POST请求到服务器进行身份验证,其内容为json格式的字符串,包含用户名和密码,若我们不使用Encoder,则代码为:
由以上代码,我们将用户名和密码格式化为json格式的字符串(当然,我们也可以通过其他工具自行格式化),然后给login方法加上@Headers,表示该POST请求为json格式的内容。若我们使用feign-gson提供的Encoder,我们可以简化我们的API,而且能确保json内容的数据类型是正确的,代码如下:
同样的,Feign提供的默认Decoder只支持Response、String、byte[]和void的response返回类型,若我们收到的response的返回类型为json等,我们需要解析为相应的对象,如上述提到过的Contributor对象。此时,我们时候用GsonDecoder可以快速达到目的,代码如下:
ErrorDecoder
除了上文提到了Decoder,Feign还专门提供ErrorDecoder组件,用于异常的response。在Feign执行request请求并收到response时,若response status code不是2xx,则认为出现异常,需要用ErrorDecoder进行处理。Feign提供默认的ErrorDecoder实现,即先检查response headers中的Retry-After,若存在则返回RetryableException,否则直接返回FeignException。
值得说明的是Feign单独提供了decode404字段,它是boolean值,当它为true且response status为404,则由Decoder组件处理;若它为false,则即使response status为404,都由ErrorDecoder处理。
Options
Options是用于设置Client中http request的一些参数,目前,Feign中的Options为Request.Options,包括connectTimeoutMillis和readTimeoutMillis两个字段。当然,我们若希望实现自己的http client,需要灵活配置更多的参数,我们也可以实现自己的Options,使之包括更多的参数,并在创建Feign对象是通过options(myOptions)方法替换。
目前,Request.Options的connectTimeoutMillis和readTimeoutMillis两个参数已经足够其支持的http client使用了。
InvocationHandlerFactory
Hystrix
Feign的子工程feign-hystrix集成了Hystrix,它实现自己的Contract、InvocationHandler和HystrixFeign,使得Feign http request具有Hystrix的功能,而且支持Fallback的降级功能。
本文不做详细叙述,要想了解,可访问项目主页:feign-hystrix和Hystrix。
- Feign介绍
- Feign介绍
- Feign
- Feign
- 疯狂Spring Cloud连载(10)REST客户端Feign介绍
- 微服务框架Spring Cloud介绍 Part4: 使用Eureka, Ribbon, Feign实现REST服务客户端
- Feign logging
- Feign基础教程
- feign入门教程
- SpringCloud(六)springcloud feign
- Spring Cloud feign
- Spring Cloud Feign诠释
- SpringCloudNetflix-Feign/Hystrix Setting
- Eureka、Ribbon和Feign
- spring cloud-feign
- Spring Cloud Feign常见问题
- Feign Hystrix 支持
- feign-使用最佳实践
- js获取日期
- Bootstrap日历DateTime Picker控件简单应用
- 简单了解Handler
- 系列:iOS开发-NSString
- 最长公共子序列问题(Longest common subsequence,LCS)
- Feign介绍
- jdk深入了解
- Windows 下openssl安装与配置
- 第一篇博客
- 浅谈数通畅联ECP与EAC的区别
- eclipse导入MyEclipse web项目无法识别的问题解决
- 递推递归练习 A 母牛的故事
- 我所理解的AsyncTask
- 软件测试怎么做的更好?