Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
在Spring Cloud中使用Feign
在了解了如何单独使用Feign后,再学习在Spring Cloud中使用Feign,将会有非常大的帮助。虽然Spring Cloud对Feign进行了封装,但万变不离其宗,只要了解其内在原理,使用起来就可以得心应手。在开始本节的讲解前,先准备Spring Cloud 的测试项目。测试案例主要有以下三个项目。
➢spring-feign-server: Eureka 服务器端项目,端口为8761,代码目录为codes)05)5.3\spring- feign-server。
➢spring-feign-provider: 服务提供者,代码目录为codes05.3)springfeign-provider,该项目可以在控制台中根据输入的端口号启动多个实例,启动8080与8081这两个端口,该项目提供以下两个REST服务。
●第一个地址为/person/ {personld)的服务,请求后返回Person 实例,Person的message属性为HTTP请求的URL。
●第二个地址为hello的服务,返回“Hello World"字符串。
➢spring-feign-invoker: 服务调用者项目,对外端口为9000,代码目录为codes(05\5.3\spring feign-invoker,本节的例子主要在该项目下使用Feign。
Spring Cloud整合Feign
为服务调用者( spring feign-ivoker)的pom.xml文件加入以下依赖:
<dependency>
<groupId>org. spr ingf ramework. cloud</groupId>
<artifactId>spr ing-cloud-starter-feign</artifactId>
</dependency>
在服务调用者的启动类中,打开Feign开关,请见代码清单5-18。
代码清单5-18;
codes(0515.3lspring-feign-invokerlsrclmainjavalorglcrazyiticloudInvokerApplication.java
aSpringBootApplication
BEnableEurekaclient
eEnableFeignClients
public class InvokerApplication {
public static void main(Stringll args) (
SpringApplicat ion.run (InvokerApplication.class,args);
接下来,编写客户端接口,与直接使用Feign类似,代码清单5-19所示为服务端接口。
代码清单5-19:
codes)0515.3spring-feign-invokerisrclmainjavalrg'crazyitcloud\PersonClient.java
aFeignClient ("spring-feign-provider") //声明调用的服务名称
public interface Personclient {
CRequestMapping (method = RequestMethod.GET, value= "/he1lo")
String hello();
与单独使用Feign 不同的是,接口使用了@FeignClient注解来修饰,并且声明了需要
调用的服务名称,本例的服务提供者名称为spring-feign-provider. 另外,接口方法使用了
@RequestMapping来修饰,根据5.2.7节的介绍可知,通过编写“翻译器(Contract)", 可
以让Feign知道第三方注解的含义,Spring Cloud也提供翻译器,会将@RequcstMapping注
解的含义告知Feign,因此我们的服务接口就可以直接使用该注解。
除了方法的@RequestMapping注解外,默认还支持@RequestParam. @RequestHeader.
@PathVariable这3个参数注解,也就是说,在定义方法时,可以使用以下方式定义参数:
@RequestMapping (method州RequestMethod. GET, value = "/he11o/ (name)")
String hello (aPathVariable("name") String name);
需要注意的是,使用了SpringCloud的“翻译器”后,将不能再使用Feign的默认注解。
接下来,在控制器中调用接口方法,请见代码清单5-20。
代码清单5-20:
codes\0515 3Ispring-feign-invoke'srcimainjavalorgcrazitclocdnvokorCorolriava
@RestController
@Configuration
public class InvokerController {
QAutowired
private PersonClient personclient;
@RequestMapping (value = "/invokeHello", method= RequestMethod.GET)
public string invokeHellol) {
return personClient. hello();
在控制器中,为其注入了PersonClient的Bean,不难看出,客户端实例的创建及维护,
Spring容器都帮我们实现了。查看本例的效果,请按以下步骤操作:
➢启动Eureka服务器( spring feign-server)。
➢启动两个服务提供者(spring feign-provider),在控制台中分别输入8080与8081端口。
➢启动一个服务调用者(spring feign-invoker),端口为9000。
➢在浏览器中输入htt:c/host,9000/inkelo可以看到服务提供者的hello服务被调用。
默认配置
SpringCloud为Feign的使用提供了各种默认属性,例如前面讲到的注解翻译器(Contract)、Feign 客户端。默认情况下,Spring 将会为Feign的属性提供以下的Bean。
➢解码器(Decoder) : Bean 名称为feignDecoder, ResponseEntityDecoder 类。
➢编码器(Encoder) : Bean 名称为feignEncoder, SpringEncoder 类。
➢日志(Logger) : Bean名称为feignLogger, SIf4jI ogger类。
➢注解翻译器(Contract) : Bean 名称为feignContract, SpringMveContract 类。
➢Feign 实例的创建者(Feign. Builder) : Bean名称为feignBuider, HystrixFeign. Builder类。Hystrix 框架将在后面章节中讲述。
➢Feign 客户端(Client) : Bean 名称为feignClient, LoadBalancerFeignClient 类。一般情况下,Spring 提供的这些Bean已经足够我们使用。
5.3.4 自定义配置
如果需要使用自已提供的Feign实现,可以在Spring的配置类中返回对应的Bean,下
面自定义一个简单的注解翻译器,代码清单5-22是一一个配置类。
代码清单52
s151-3rplsgn-fgigninovorerrainivalagrgyayitcloudocontractMtyCofg java
gConfiguration
public class MyConfig {
返回一个自定义的注解翻译器
/
aBean
public Contract feignContract() 1
return new MyContract();
配置类中返回了一个MyContract实例,MyContract 是我们自定义的“翻译器”,实现请见代码清单5-23。
代码清单5-23:
codsl53-siin-ieigivovoersrcainijaoglgcrazytloudcontractMyContractjava
自定义Contract
@author杨恩雄
public class MyContract extends Spr ingMvcContract
用于处理方法级的注解
protected void processAnnotat ionOnMe thod (MethodMetadata data,
Annotation annotation, Method method) (
//调用父类的方法,让其支持@RequestMapping注解
super .procea sAnnotationOnMethod (data, annotation, method);
1/是MyUrl注解才进行处理
if (MyUrl,class . isInstance (annotation))
//获取注解的实例
MyUrl myUrIAnn = method. getAnnotation (MyUr1.class);
11获取配置的HTTP方法
String httpMethod - myUrlAnn. method();
//获取服务的url
String url- myUr1Ann.ur10;
//将值设置到模板中
data.cemplate () .method (httpMethod) ;
data.template() append(url);
在前面的章节中,我们也实现过自定义的Contract,与前面实现的Contract不同的是,本例的MyContract继承了SpringMvcContract,在重写poesotatinOonMethordo方法时,调用了父类的processAnnotationOnMethod.简单点说,我们实现的这个Contract, 除了支持Spring的注解外,还支持我们自定义的@MyUrl注解。@MyUrl注解与前面章节中介绍的一致,请见代码清单5-24。
代码清单5-24:
cods0515./sping-geigninvoversrcrmainjavalorglcrayiticlodldcontrartryUrijava
@Target (METHOD)
@Retention (RUNTIME)
publlc einterface MyUrl (临
//定义url与method属性
String url();
String method();
可选配置
Spring 为这些配置提供了默认的Bean。除了这些配置外,还有如下的配置,Spring 并没有提供默认的Bean。
➢Logger.Level: 接口日志的记录级别,相当于调用了Feign.Builder 的logLevel方法,
➢Retryer: 重试处理器,相当于调用了Feign.Builder 的retryer方法。
➢ErrorDecoder: 异常解码器,相当于调用了Feign. Builder的errorDecoder 方法。
➢Request.Options: 设置请求的配置项,相当于调用了Feign Builder的options方法。
➢Collection<Requestlnterceptor>: 设置请求拦截器,相当于调用了Feign.Builder 的
requestInterceptors方法。
➢SetterFactory: 该配置与Hystrix框架相关,将在后面章节详细讲述。
以上的配置,如果没有提供对应的Bean,则不会被设置。在此需要注意的是请求拦截器,由于可以设置多个请求拦截器,在创建Bean 时也可以创建多个,返回类型需要为RequestInterceptor或者实现类。要设置多个请求拦截器。
压缩配置
Feign支持对请求和响应进行压缩处理,默认使用GZIP进行压缩,压缩操作在Feign
的请求拦截器中实现。可以在配置文件中加入以下配置。
➢figncoresonrcquest. enabled:设置为true开启请求压缩。
➢figncompesson.response. enabled:设置为true开启响应压缩。
➢figncoreson.requestmimne types:数据类型列表,默认值为textxml, aplcatinxoml,
application/json。
➢fig.compessoneguestsmin-repuest-size: 设置请求内容的最小阈值,默认值为2048。