关于Spring Cloud Feign,一个核心概念是命名客户端(named client)。每个feign client可以被理解成是一整套组件的一部分,这套组件一块工作,按需跟远程服务器发生联系,这整套组件有一个名字,就是应用开发人员通过@FeignClient所指定的名字。Spring Cloud根据FeignClientsConfiguration配置,针对每一个命名的feign客户端,将它的这整套组件创建为一个ApplicationContext实例存在。这里面包含了一个feign.Decoder,一个feign.Encoder和一个feign.Contract。并且使用注解@FeignClient的属性contextId可以覆盖这整套组件的名称。
通过使用@FeignClient注解属性configuration增加额外的配置,Spring Cloud允许你完全控制feign客户端。例子如下 :
// 这里 FooConfiguration 会叠加在缺省 FeignClientsConfiguration 之上
// 对 feign client stores 生效
@FeignClient(name = "stores", configuration = FooConfiguration.class)
public interface StoreClient {
//..
}
该例子中的feign客户端会结合考虑FeignClientsConfiguration配置和自定义配置FooConfiguration最终生成,并且FooConfiguration配置中的定义优先级高。
注意 :
FooConfiguration不必要使用注解@Configuration。不过如果FooConfiguration使用了注解@Configuration,则注意把它从@ComponentScan中排除掉,要不然该配置会被@ComponentScan包含进来,这样它就会变成feign.Decoder,feign.Encoder,feign.Contract等组件的缺省来源。想避免FooConfiguration被@ComponentScan看到,可以将它放到一个独立的,跟任何@ComponentScan/@SpringBootApplication可见包都不重叠的包中。或者将它明确地从@ComponentScan注解中排除。
注意 :
serviceId属性现在已经不建议使用了,推荐使用name。
注意 :
@FeignClient注解属性contextId可以用于修改整个套组ApplicationContext的名字,它会覆盖客户端名称的别名,也会被用作该feign客户端配置bean名称的一部分。
注意 : 以前使用
url属性,不需要name属性。现在必须要使用name属性。
@FeignClient的name/url属性值可以使用占位符,如下所示:
@FeignClient(name = "${feign.name}", url = "${feign.url}")
public interface StoreClient {
//..
}
Spring Cloud Netflix 为feign客户端缺省提供以下bean组件:
BeanType | beanName | ClassName |
|---|---|---|
Decoder | feignDecoder | ResponseEntityDecoder (包了一个SpringDecoder) |
Encoder | feignEncoder | SpringEncoder |
Logger | feignLogger | Slf4jLogger |
Contract | feignContract | SpringMvcContract |
Feign.Builder | feignBuilder | HystrixFeign.Builder |
Client | feignClient | 如果启用了Ribbon会是LoadBalancerFeignClient,否则会使用缺省的client |
把OkHttpClient或者ApacheHttpClient 放在classpath中,并且相应设置feign.okhttp.enabled 或者feign.httpclient.enabled 为true, 那就会使用相应的这些HTTP客户端。想定制HTTP客户端的话,使用ApacheHttpClient时,你可以提供一个类型为ClosableHttpClient的bean;使用OK HTTP的话,提供一个类型为OkHttpClient的bean。
缺省情况下,Spring Cloud Netflix没有给feign提供以下bean组件,但是它仍然会从应用上下文中查找这些bean组件用于创建feign客户端 (这里其实给开发人员提供了定制feign客户端的机会):
Logger.LevelRetryerErrorDecoderRequest.OptionsCollection<RequestInterceptor>SetterFactory
在@FeignClient配置(比如上面提到的配置FooConfiguration)中定义这里描述的任何一种类型的bean,你就可以覆盖框架缺省提供的这种类型的bean。比如 :
@Configuration
public class FooConfiguration {
@Bean
public Contract feignContract() {
return new feign.Contract.Default();
}
@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("user", "password");
}
}
通过该例子,开发人员指定使用feign.Contract.Default而不再使用Spring Cloud缺省的SpringMvcContract。并且开发人员往RequestInterceptor集合中增加了一个自定义的RequestInterceptor:BasicAuthRequestInterceptor。
@FeignClient也可以通过配置文件配置 , 如下例子所示 :
application.yml配置文件内容 :
feign:
client:
config:
feignName:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
errorDecoder: com.example.SimpleErrorDecoder
retryer: com.example.SimpleRetryer
requestInterceptors:
- com.example.FooRequestInterceptor
- com.example.BarRequestInterceptor
decode404: false
encoder: com.example.SimpleEncoder
decoder: com.example.SimpleDecoder
contract: com.example.SimpleContract
通过注解@EnableFeignClients的属性defaultConfiguration可以为所有feign客户端提供缺省配置,配置方式跟上面提到的方式类似。区别是缺省属性是面向所有feign客户端的。
如果你喜欢使用配置文件配置所有@FeignClient,你可以使用缺省配置属性,也就是feign客户端名称为default,例子如下所示 :
application.yml配置文件内容 :
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: basic
如果你既定义了@Configuration配置类bean又使用了配置属性,配置属性会被优先使用,它会覆盖@Configuration配置类bean中的值。但是如果你想指定使用@Configuration,可以设置feign.client.default-to-properties为false。
如果你想在RequestInterceptor中使用ThreadLocal绑定变量,你需要将Hystrix的线程隔离策略设置为SEMAPHORE或者在Feign中禁用Hystrix:
application.yml`配置文件内容 :
# 禁用Feign中的Hystrix:
feign:
hystrix:
enabled: false
# 设置线程隔离级别为SEMAPHORE:
hystrix:
command:
default:
execution:
isolation:
strategy: SEMAPHORE
如果你想创建多个同名或者url相同的feign客户端以确保它们指向同一个服务器但是又要它们使用不同的配置,那么我们必须使用不同的contextId以避免这些配置bean的名字冲突。例子如下所示 :
@FeignClient(contextId = "fooClient", name = "stores", configuration = FooConfiguration.class)
public interface FooClient {
//..
}
@FeignClient(contextId = "barClient", name = "stores", configuration = BarConfiguration.class)
public interface BarClient {
//..
}
本文深入探讨SpringCloud Feign客户端的核心概念,包括命名客户端、组件配置及自定义选项。介绍了如何通过注解和配置文件定制Feign客户端,实现高级控制。
952

被折叠的 条评论
为什么被折叠?



