Spring Cloud OpenFeign文档

宝剑锋从磨砺出,梅花香自苦寒来。这篇文章主要讲述Spring Cloud OpenFeign文档相关的知识,希望能为你提供帮助。


Spring Cloud OpenFeign

  1. 声明式REST客户端:Feign
Feign 是一个声明式网络服务客户端, 它使得书写网络服务器更加简单。通过使用Feign创建一个接口并且对他进行声明。具有可插拔声明支持,包括feign声明和JAX-RS声明。Feign同样支持可插拔式的编码器和解码器。Spring Cloud同样添加对Spring MVC注解的支持并且使用在Spring Web中默认使用的HttpMessageConverters.Spring Cloud在使用Feign时,默认集成了Eureka注册中心,也集成了Spring Cloud LoadBalancer 来提供一个负载均衡客户端。
1.1.怎样加载Feign
使用Spring-cloud-starter-openfeign.
一个应用实例
@SPringBootApplication
@EnableFeignClients
public class Application
public static void main(String []args)
SpringApplication.run(Appllication.class, args);


StoreClient.java
@FeignClient("stores")
public interface StoreClient
@RequestMapping(method=RequestMethod.GET, value="https://www.songbingjia.com/stroes")
List< Store> getStores();
@RequestMapping(method=RequestMethdod.POST, value="https://www.songbingjia.com/stores/stroeId", consumers="application/json")
Store update(@PathVariable("storeId") Long storeId, Store store);

在@FeignCLient注解中, 字符串("stroes")是任意一个客户端的名字, 通常被用作创建一个Spring Cloud LoadBalancer client. 你也可以指定一个URL使用“url”属性(主机名)。应用上下文中Bean的名称是接口的完全限定名。要指定feign client的别名可以使用@FeignClient注解中的 限定值。
以上的负载均衡器客户端,想要发现“stroes”服务的物理地址。如果你使用的是feign,那么只需要简单注册即可,rugosa不是,也可以简单的在外部配置中配置服务列表。
1.2. 覆盖默认的Feign配置
Spring Cloud Feign支持的一个中心思想是指定客户端。每一个feign客户端都是组件集成的一部分,他们在需要时一同工作,与远程服务取得联系。Spring Cloud 通过使用@FeignClientsConfiguration注解为每一个指定的客户端再需要的时候创建了一个集合作为应用上下文。这其中包含了一个解码器,编码器和一个使用协议。通过使用@FeignClient注解中的contextId属性来覆盖集合的名称。通过使用@FeignClient声明额外的配置,你被允许取得Feign 客户端的完全控制权。例如
@FeignClient(name="stores", configuration=FooConfiguration.class)
public interface StoreClient
//..

在这种情况下, 客户端是由存在于FeignClientsConfiguration中的组件和FoConfiguration中的任意组件构成的(后者将覆盖前者)。

FooConfiguration不需要用@Configuration注解。然而,如果已经被注解。那么小心,将它从任何@ComponentScan注解下的路径剔除。否则他将成为feign解码器,编码器和协议的默认来源。
【Spring Cloud OpenFeign文档】serviceId属性被启用,转而以name属性替代
以前使用url属性不需要使用name属性,现在则必须使用
占位符在name和url属性中是被允许使用的。
@FeignClient(name = "$feign.name", url = "$feign.url")
public interface StoreClient
//..

Spring Cloud OpenFeign 默认为feign提供一下bean:
  • Decoder: feignDecoder: ResponseEntityDecoder(被封装成一个Spring Decoder)
  • Encoder:feignEncoder:SpringEncoder
  • Logger:feignEncoder:Slf4jLogger
  • Contract feignContract: SpringMvcContract
  • Feign.Builder feignBuilder: HystrixFeign.Builder
  • Client: feignClient: 如果负载均衡器在classpath中,FeignBlockingLoadBalancerClient正在使用中,如果不在那就是使用的默认feign客户端。
OKHTTPClient 和 APacheClient 可以通过设置feign.okhttp.enabled和feign.httpclient.enabled为true使用。
默认情况下, Spring Cloud Netflix没有为feign提供一下bean.但是仍然可以通过在上下文文中寻找这些bean来创建feign client.:
  • Logger.Level
  • Retryer
  • ErrorDecoder
  • Request.Options
  • Collection
  • SetterFactory
  • QueryMapEncoder
    创建这些类型之一的bean并将其放在@FeignClient配置中(如上面的FooConfiguration),可以覆盖所描述的每个bean.例如:
@Configuration
public class FooConfiguration
@Bean
public Contract feignContract()
return new feign.Contract.Default();


@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor()
return new BasicAuthRequestInterceptor("user", "password");


这段代码使用eign.Contract.Default取代了SpringMvcContract并且添加了一个RequestInterceptor到RequestInterceptor集合中
@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属性配置所有的@FeignClient。你可以创建默认的feign名来创建配置。
application.yml

feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel:

如果你同时使用@Configuration和在application。yml中配置属性, 码么配置属性将会胜出生效。如果你想要改变优先级, 那么可以将feign.client.default-to-properties的值改为false
如果您需要在您的RequestInterceptor中使用ThreadLocal绑定变量,那么您需要将Hystrix的线程隔离策略设置为‘SEMAPHORE’,或者在Feign中禁用Hystrix。
application.yml

# To disable Hystrix in Feign
feign:
hystrix:
enabled: false

# To set thread isolation to SEMAPHORE
hystrix:
command:
default:
execution:
isolation:
strategy:

如果我们想创建多个具有相同名称或url的伪客户端,以便它们指向相同的服务器,但每个服务器都具有不同的自定义配置,那么我们必须使用@FeignClient的contextId属性,以避免这些配置bean的名称冲突。

  • 可以用
@FeignClient(contextId = "fooClient", name = "stores", configuration = FooConfiguration.class)
public interface FooClient
//..

@FeignClient(contextId = "barClient", name = "stores", configuration = BarConfiguration.class)
public interface BarClient
//..

1.3. 手动的创建Feign客户端, 没兴趣
某些情况下,可能需要以一种不可能使用上述方法的方式自定义您的feign客户端。在这种情况下,您可以使用Feign Builder API创建客户端。下面是一个例子,它创建了两个具有相同接口的伪客户端,但每个feign客户端都配置了一个单独的请求拦截器。
@Import(FeignClientsConfiguration.class)
class FooController

private FooClient fooClient;

private FooClient adminClient;

@Autowired
public FooController(Decoder decoder, Encoder encoder, Client client, Contract contract)
this.fooClient = Feign.builder().client(client)
.encoder(encoder)
.decoder(decoder)
.contract(contract)
.requestInterceptor(new BasicAuthRequestInterceptor("user", "user"))
.target(FooClient.class, "https://PROD-SVC");

this.adminClient = Feign.builder().client(client)
.encoder(encoder)
.decoder(decoder)
.contract(contract)
.requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
.target(FooClient.class, "https://PROD-SVC");


在上面的例子中,FeignClientsConfiguration.class是Spring Cloud Netflix提供的默认配置。
PROD-SVC是客户机将向其发出请求的服务的名称。
Feign Contract对象定义接口上有效的注释和值。autowired Contract
bean提供了对SpringMVC注解的支持,而不是默认的佯装本地注解。
1.4. Feign Hystrix Support
如果Hystrix位于类路径上,则使用feign.hystrix.enabled=true, Feign会用一个断路器来封装所有的方法。还可以返回com.netflix.hystrix.HystrixCommand。这允许您使用响应模式(通过调用. toobservable()或.observe()或异步使用(通过调用.queue())。要在每个客户端基础上禁用Hystrix支持,请创建一个普通的伪代码。具有“原型”作用域的生成器,例如
@Configuration
public class FooConfiguration
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder()
return Feign.builder();


在Spring Cloud
Dalston发布之前,如果Hystrix在类路径上,那么在默认情况下,Feign会将所有方法封装在一个断路器中。在Spring Cloud
Dalston中更改了此默认行为,以支持选择进入方法。
1.5. Feign Hystrix Fallbacks
Hystrix支持fallback的概念:当circuit打开或出现错误时执行的默认代码路径。要为给定的@FeignClient启用fallback,请将fallback属性设置为实现fallback的类名。您还需要将实现声明为Spring bean(@Component)。
@FeignClient(name = "hello", fallback = HystrixClientFallback.class)
protected interface HystrixClient
@RequestMapping(method = RequestMethod.GET, value = "https://www.songbingjia.com/hello")
Hello iFailSometimes();


static class HystrixClientFallback implements HystrixClient
@Override
public Hello iFailSometimes()
return new Hello("fallback");


如果需要访问回退触发的原因,可以在@FeignClient中使用fallbackFactory属性。
@FeignClient(name = "hello", fallbackFactory = HystrixClientFallbackFactory.class)
protected interface HystrixClient
@RequestMapping(method = RequestMethod.GET, value = "https://www.songbingjia.com/hello")
Hello iFailSometimes();


@Component
static class HystrixClientFallbackFactory implements FallbackFactory< HystrixClient>
@Override
public HystrixClient create(Throwable cause)
return new HystrixClient()
@Override
public Hello iFailSometimes()
return new Hello("fallback; reason was: " + cause.getMessage());

;


在Feign中fallback的实现和Hystrixfallback的工作方式有一定的局限性。对于返回com.netflix.hystrix.HystrixCommand和rx.Observable的方法,目前不支持fallback。
1.6. Feign和 @Primary
当使用Feign和Hystrix fallbacks时,同一类型的ApplicationContext中有多个bean。这将导致@Autowired不能工作,因为没有一个bean,或者一个标记为primary bean。为了解决这个问题,Spring Cloud Netflix将所有 feign 实例标记为@Primary,因此Spring框架将知道注入哪个bean。在某些情况下,这可能是不可取的。要关闭此行为,请将@FeignClient的主属性设置为false。
@FeignClient(name = "hello", primary = false)
public interface HelloClient
// methods here

1.7 feign继承支持
Feign通过单继承接口支持样板api。这允许将通用操作分组到方便的基本接口中
UserService.java

public interface UserService

@RequestMapping(method = RequestMethod.GET, value ="https://www.songbingjia.com/users/id")
User getUser(@PathVariable("id") long id);

UserResource.java
@RestController
public class UserResource implements UserService


UserClient.java
package project.user;

@FeignClient("users")
public interface UserClient extends UserService


通常不建议在服务器和客户机之间共享接口。它引入了紧密耦合,并且在当前的形式下也不能使用Spring MVC(方法参数映射不是继承的)
1.8. Feign request/response compression
您可以考虑为您的feign请求启用请求或响应GZIP压缩。您可以通过启用其中一个属性来做到这一点
feign.compression.request.enabled=true
feign.compression.response.enabled=true

Feign请求压缩为您提供类似于web服务器的设置
feign.compression.request.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048

这些属性允许您选择压缩媒体类型和最小请求阈值长度。对于除OkHttpClient外的http客户端,可以启用默认的gzip解码器来解码UTF-8编码的gzip响应
feign.compression.response.enabled=true
feign.compression.response.useGzipDecoder=true

1.9. Feign logging
将为创建的每个feign客户端创建一个日志程序。默认情况下,日志程序的名称是用于创建Feign客户端的接口的完整类名。feign日志只对调试级别有响应。
application.yml
logging.level.project.user.UserClient:

1.10. Feign @QueryMap support
OpenFeign @QueryMap注释支持将pojo用作GET参数映射。不幸的是,默认的OpenFeign QueryMap注释与Spring不兼容,因为它缺少值属性。Spring Cloud OpenFeign提供了一个等价的@SpringQueryMap注释,用于将POJO或Map参数注释为查询参数映射。例如,Params类定义了参数param1和param2
// Params.java
public class Params
private String param1;
private String param2;

// [Getters and setters omitted for brevity]

下面的feign客户端通过使用@SpringQueryMap注释来使用Params类

@FeignClient("demo")
public interface DemoTemplate

@GetMapping(path = "/demo")
String demoEndpoint(@SpringQueryMap Params params);

如果您需要对生成的查询参数映射有更多的控制,您可以实现一个定制的QueryMapEncoder bean。
  1. Configuration properties
    可以在应用程序中指定各种属性。属性文件,在您的应用程序中。yml文件,或作为命令行开关。本附录提供了通用Spring Cloud OpenFeign属性的列表,以及对使用它们的底层类的引用。
    ???https://cloud.spring.io/spring-cloud-openfeign/reference/html/appendix.html??



    推荐阅读