本文共 5364 字,大约阅读时间需要 17 分钟。
官网地址:
Feign是一个声明式的Web服务客户端,让编写Web服务客户端变得非常容易,只需 创建一个接口并在接口上添加注解即可。
Spring Cloud提供的Feign增强版,使得Feign支持Spring MVC的注解,开发更容易了。
创建一个model工程作为服务消费者,即eureka-feign-client
。
org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.cloud spring-cloud-starter-openfeign
在启动类中添加 @EnableFeignClients
注解开启Feign的功能。
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;import org.springframework.cloud.openfeign.EnableFeignClients;import org.springframework.context.annotation.Bean;import org.springframework.web.client.RestTemplate;@SpringBootApplication@EnableEurekaClient// 开启Feign的功能@EnableFeignClientspublic class EurekaFeignClientApplication { public static void main(String[] args) { SpringApplication.run(EurekaFeignClientApplication.class, args); }}
配置文件appication.yml
server: port: 8083spring: application: name: eureka-feign-clienteureka: client: serviceUrl: defaultZone: http://localhost:8100/eureka/
定义一个Feign接口,在接口上加@FeignClient
注解来声明一个 Feign Client,
value
为远程调用其他服务的服务名。 import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;// 申明这是一个Feign客户端,并且指明服务id@FeignClient(value = "eureka-client")public interface FeignClientInter { // 这里定义了类似于SpringMVC用法的方法,就可以进行RESTful方式的调用了 @GetMapping(value = "/hello") String sayHelloFromClient();}
通过上面定义的Feign客户端来消费服务。
import com.yq.feign.service.FeignClientInter;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HelloController { @Autowired(required = false) FeignClientInter feignClientInter; @GetMapping("/feign") public String demo() { return feignClientInter.sayHelloFromClient(); }}
启动测试
在浏览器上多次访问http://127.0.0.1:8083/feign
,浏览器交替显示,说明集成了Ribbon负载均衡。 OpenFeign默认等待1秒钟。超过后报错。
# 设置feign客户端超时时间(OpenFeign默认支持ribbon)ribbon: # 指的是建立连接所用的时间,适用于网络状态正常的情况下,两端连接所用的时间 ReadTimeout: 5000 # 指的是建立连接后从服务器读取到可用资源所用的时间 ConnectTimeout: 5000
import feign.Logger;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class FeignConfig { @Bean public Logger.Level feignLoggerLevel() { // 请求和响应的头信息,请求和响应的正文及元数据 return Logger.Level.FULL; }}
YML文件里需要开启日志的Feign客户端:
logging: level: # feign日志以什么级别监控哪个接口 com.demo.service.PaymentFeignService: debug
后台查看日志:
Feign 是一个伪 Java Http 客户端 , Feign 不做任何的请求处理。 Feign 通过处理注解生成 Request 模板,从而简化了 Http API 的开发。
开发人员可以使用注解的方式定制 Request API 模板。在发送 HttpRequest 请求之前 , Feign 通过处理注解的方式替换掉 Request 模板中的参数,生成真正的 Request ,并交给 Java Http 客户端去处理 。利用这种方式,开发者只需要关注 Feign 注解模板的开发 ,而不用关注 Http 请求本身,简化了 Http 请求的过程 ,使得 Http 请求变得简单和容易理解。Feign 通过包扫描注入 FeignClient 的 Bean ,该源码在 FeignClientsRegistrar
类中 。首先在程序启动时,会检查是否有@EnableFeignClients 注解,如果有该注解,则开启包扫描,扫描被@FeignClient 注解的接口 。
当程序的启动类上有@EnableFeignClients注解。在程序启动后,程序会通过包扫描将有@FeignClient 注解修饰的接口得到一个BeanDefinition ,并将BeanDefinition 注入 IoC 容器中。org.springframework.cloud.openfeign.FeignClientsRegistrar#registerFeignClients
通过 JDK 的代理,当调用 FeignClient 接口里面的方法时,该
方法会被拦截,源码在ReflectiveFeign
类。 在 SynchronousMethodHandler
类进行拦截处理,会根据参数生成RequestTemplate 的Http请求模板对象,然后调用 executeAndDecode()方法,该方法通过 RequestTemplate 生成 Request请求对象,然后用 HttpClient 获取 Response ,即通过 HttpClient 进行 Http 请求来获取响应。
首先查看 FeignRibbonClient 的自动配置类 FeignRibbonClientAutoConfiguration
,@Import 自动注入三个请求框架,从名字上可以看出默认使用最后一个Client。
HttpClientFeignLoadBalancedConfigurationOkHttpFeignLoadBalancedConfigurationDefaultFeignLoadBalancedConfiguration
new Client.Default()
来创建Client的。 HttpClientFeignLoadBalancedConfiguration
和OkHttpFeignLoadBalancedConfiguration
源码。 @ConditionalOnClass(ApacheHttpClient.class)
和@ConditionalOnClass(OkHttpClient.class)
注解可知道,只需要在 POM 文件加上HttpClient或者OkHttpClient 的 Classpath 即可 。 另外需要在配置文件 application.yml 中配置feign.httpclient.enabled
或者feign.okhttp.enabled
为 true,从 HttpClientFeignLoadBalancedConfiguration类上的@ConditionalOnProperty注解可知,这个配置可以不写,因为在默认的情况下就为true,如果使用OkHttp,必须配置feign.okhttp.enabled
,因为OkHttpFeignLoadBalancedConfiguration类上的@ConditionalOnProperty注解未设置为true。 POM 文件加上 feign-httpclient 的依赖, Feign 就会采用 HttpClient 作为网络请求框架。
com.netflix.feign feign-okhttp RELEASE
POM 文件加上 feign-okhttp 的依赖, Feign 就会采用 OkHttp 作为网络请求框架。
com.netflix.feign feign-httpclient RELEASE
如果容器中三个Client都存在,Feign会默认根据@Import注入类的顺序来选择Client。在LoadBalancerFeignClient
类中可以看出使用了哪个Client。
转载地址:http://igdhb.baihongyu.com/