SpringCloud(十):声明式RESt客户端:Feign

说明:本文是个人在学习Feign模块在拜读官方资料时突发奇想有种翻译的冲动,然后便成此文,仅作参考。

原文地址:http://cloud.spring.io/spring-cloud-static/Camden.SR1/#spring-cloud-feign

声明式REST客户端:Feign

Feign是一个声明式的Web服务客户端。它使得Web服务客户端的写入更加方便。

使用Feign创建一个界面并对其进行注释;

具有可插拔注释支持,包括Feign注释和JAX-RS注释;

支持可插拔编码器和解码器;

Spring Cloud增加了对Spring MVC注释的支持,并且使用了在Spring Web中默认使用的相同的HttpMessageConverter。Spring Cloud集成了Ribbon和Eureka,在使用Feign时提供了负载均衡的http客户端。

如何添加Feign

要在项目中添加Feign,请使用组org.springframework.cloud和artifact id spring-cloud-starter-feign的启动器。有关使用当前的Spring Cloud发布列设置构建系统的详细信息,请参阅Spring Cloud Project page

示例spring boot app

@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableEurekaClient
@EnableFeignClients
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

StoreClinet.java

@FeignClient("stores")
public interface StoreClient {
    @RequestMapping(method = RequestMethod.GET, value = "/stores")
    List<Store> getStores();

    @RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
    Store update(@PathVariable("storeId") Long storeId, Store store);
}
在@FeignClient注释中,String值(以上“存储”)是一个任意客户端名称,用于创建功能区负载平衡器(有关Ribbon支持的详细信息,请参考下文)。您还可以使用url属性(绝对值或只是主机名)指定URL。应用程序上下文中的bean的名称是该接口的完全限定名称。还创建了一个别名,它是'name'属性加'FeignClient'。对于上面的实例,可以使用@Qualifier("storesFeignClient")来引用该bean.如果要更改默认的@Qualifier值,可以使用@FeignClient中的限定符值来完成此操作。

上面的Ribbon客户端将要发现“store”服务的物理地址。如果您的应用程序是Eureka客户端,那么它将解决Eureka服务注册表中的服务。如果您不想使用Eureka,您可以在外部配置中简单地配置服务列表。(例如,参见上文

覆盖Feign默认值

Spring Cloud的Feign支持的一个中心概念就是命名客户端。每个feign客户端都是组合的组件的一部分,它们一起工作以按需联系远程服务器,并且该组件具有一个名字,这个名字您将其作为使用@FeignClient注释的应用程序开发人员。Spring Cloud使用FeignClientsConfiguration为每个命名的客户端根据需要创建一个新的集合作为ApplicationContext。这包含(其中包括)一个feign.Decoder,一个feign.Encoder和一个feign.Contract。
Spring Cloud可以通过使用@FeignClient声明额外的配置(在FeignClientsConfiguration之上)来完全控制feign客户端。例:
@FeignClient(name = "stores", configuration = FooConfiguration.class)
public interface StoreClient {
    //..
}
在这种情况下,客户端由已在FeignClientsConfiguration中的组件以及FooConfiguration中的任何组件组成(后者将覆盖前者)。
警告:
FooConfiguration必须使用@Configuration注释。但请注意,它不在主应用程序上下文的@ComponentScan中,否则将用于每个@FeignClient。如果使用@ComponentScan(或@SpringBootApplication),则需要采取措施避免包含(例如将其放在一个单独的,不重叠的包中,或者指定要在@ComponentScan中显式扫描的包)。
注意:
serviceId属性现在已被弃用,有利于name属性。
警告:
以前,使用url属性,不需要name属性。现在要使用名称。

名称和网址属性支持占位符。
@FeignClient(name = "${feign.name}", url = "${feign.url}")
public interface StoreClient {
    //..
}

Spring Cloud Netflix默认为feign(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,否则将使用默认的feign客户端。
可以通过将feign.okhttp.enabled或feign.httpclient.enabled设置为true并将它们放在类路径上来使用OKHttpClient和ApacheHttpClient feign客户端。
Spring Cloud Netflix默认情况下不提供以下bean,但是仍然从应用程序上下文中查找这些类型的bean以创建feign客户端。
*Logger.Level
*Retryer
*ErrorDecoder
*Request.Options
*Collection<RequestInterceptor>
创建一个类型的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");
    }
}
这将使用feign.Contract.Default替换SpringMvcContract,并将RequestInterceptor添加到RequestInterceptor的集合中。
可以在@EnableFeignClients属性defaultConfiguration中以与上述相似的方式指定默认配置。不同之处在于,此配置将适用于所有feign客户端。

Feign Hystrix支持

如果Hystrix在类路径上,默认情况下,Feign将使用断路器包装所有方法。返回com.netflix.hystrixCommand也可用。这允许您使用反应模式(调用.toObservable()或.observe()或异步使用(调用.queue())。
要禁用Feign的Hystrix支持,请设置feign.hystrix.enabled=false.
在每个客户端基础上禁用Hystrix支持创建一个带有“原型”scope的vanilla Feign.Builder
@Configuration
public class FooConfiguration {
    @Bean
	@Scope("prototype")
	public Feign.Builder feignBuilder() {
		return Feign.builder();
	}
}

Feign Hystrix回退

Hystrix支持回退概念:当回路打开或执行错误时执行的默认代码路径。要为给定的@FeignClient启用回退,将fallback属性设置为实现回退的类名。
@FeignClient(name = "hello", fallback = HystrixClientFallback.class)
protected interface HystrixClient {
    @RequestMapping(method = RequestMethod.GET, value = "/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 = "/hello")
	Hello iFailSometimes();
}

@Component
static class HystrixClientFallbackFactory implements FallbackFactory<HystrixClient> {
	@Override
	public HystrixClient create(Throwable cause) {
		return new HystrixClientWithFallBackFactory() {
			@Override
			public Hello iFailSometimes() {
				return new Hello("fallback; reason was: " + cause.getMessage());
			}
		};
	}
}
警告:
在Feign中的回退实现和Hystrix回退工作方式有局限性。当前返回com.netflix.hystrix.HystrixCommand和rx.Observable的方法目前不支持回退。

Feign继承支持

Feign通过单继承接口支持样板apis。这样就可以将常用操作分成方便的基本界面。
UserService.java
public interface UserService {

    @RequestMapping(method = RequestMethod.GET, value ="/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(方法参数映射不被继承)。
Feign 请求/响应压缩
您可以考虑为您的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
这些属性可以让您对压缩介质类型和最小请求阈值长度有选择性。

Feign日志记录

为每个创建的Feign客户端创建一个记录器。默认情况下,记录器的名称是用于创建Feign客户端的接口的完整类名。Feign logging仅响应DEBUG级别。

application.yml
logging.level.project.user.UserClient: DEBUG

您可以为每个客户端配置的Logger.Level对象告诉Feign记录多少。选择是:
*NONE,无记录(DEFAULT)。
*BASIC,只记录请求方法和URL以及响应状态代码和执行时间。
*HEADERS,记录基本信息以及请求和响应标头。
*FULL,记录请求和响应的头文件,正文和元数据。
例如,以下将Logger.Level设置为FULL:
@Configuration
public class FooConfiguration {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}


















猜你喜欢

转载自blog.csdn.net/u013037201/article/details/77124590