Spring整合Feign
Spring Cloud对Feign进行了封装,我们通过一个例子,说明下如何在Spring中整合Feign。
测试案例
测试案例主要分为三个部分:
- spring-feign-server:Eureka服务器端项目,端口为8761,提供服务注册,查询功能
- spring-feign-provider:服务提供者。此项目支持通过指定不同的端口号启动多个不同的实例
- spring-feign-invoker:服务调用者。它会通过spring-feign-server提供的接口查询到spring-feign-provider提供的服务列表,发起调用,对外提供9000端口服务。
spring-feign-server
本项目的依赖为:
1 | <dependencies> |
仅仅作为一个Eureka服务器运行,因此,不需要太复杂的逻辑,启动类如下所示:
1 |
|
配置文件如下:
1 | server: |
spring-feign-provider
项目的依赖为:
1 | <dependencies> |
对外提供了/hello和/person/{personId}两个REST服务
1 |
|
Person类如下:
1 | public class Person { |
启动类如下:
1 |
|
配置文件如下:
1 | spring: |
spring-feign-invoker
Invoker项目的依赖为
1 | <dependencies> |
它内部封装了调用provider提供的两个REST服务的逻辑,分别在HelloClient和PersonClient中
HelloClient
1 |
|
PersonClient
1 | //声明调用的服务名称 |
Person
1 | public class Person { |
在两个XXXClient中,我们使用了注解FeignClient,并且声明了需要调用的服务名称。另外,我们还使用了Spring的注解RequestMapping,这意味着,我们需要一个翻译器Contract,让Feign知道Spring的这个注解的含义。
最后,除了@RequestMapping注解外,默认还支持@RequestParam、@RequestHeader和@PathVariable这三个参数注解。
需要注意的是,使用了Spring Cloud的“翻译器”后,将不能再使用Feign的默认注解。
让我们看一下,“翻译器”
1 | public class MyContract extends SpringMvcContract { |
这边的翻译器继承了SpringMVCContract,并且重载了processAnnotationOnMethod方法,但是,在方法的最前面又调用了父类方法。这就意味着,它不仅支持翻译Spring的注解,也支持翻译自定义的MyUrl注解。
MyUrl
1 |
|
接着,我们过一下Controller的代码
1 |
|
上面使用了@Autowired注解,注入了HelloClient和PersonClient。
配置文件
1 | server: |
启动类
1 |
|
启动
我们按照下面的顺序启动三个组件
- spring-feign-server
- spring-feign-provider
- spring-feign-invoker
启动完毕后,可以在Eureka的管理界面看到注册的三个服务
测试
可以在浏览器中输入http://localhost:9000/invokeHello或者http://localhost:9000/router
我们可以得到下面的结果
可以看到,SpringCloud提供的Feign客户端是具有负载均衡功能的。Spring Cloud实现的Feign客户端,类名为LoadBalancerFeignClient,在该类中维护者与SpringClientFactory相关的实例。通过SpringClientFactory可以获取负载均衡器,负载均衡器会根据一定的规则来选取处理请求的服务器,最终实现负载均衡功能。
我们还可以通过Spring的@Bean注解实现自定义配置
1 |
|
要实现自定义的“翻译器”或者拦截器,只要实现一个返回对应类型的方法,加上注解@Bean即可。比如,实现一个返回Contact的方法,用@Bean标记,就可以自定义“翻译器”了。拦截器也同样道理,具体可参见上面的代码。