Feign是一个声明性的Web服务客户端。 它使编写Web服务客户端变得更容易。 要使用Feign需要创建一个接口并添加相应的注释。 它具有可插入的注释支持,包括Feign注释和JAX-RS注释。 Feign还支持可插拔编码器和解码器。 Spring Cloud增加了对Spring MVC注释的支持,并使用了Spring Web中默认使用的相同HttpMessageConverters【重点】。Spring Cloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。
org.springframework.cloud
spring-cloud-starter-feign
应用实例
springboot启动类
@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableEurekaClient
//启动feign
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
调用接口
//stores 被调用方无名名
@FeignClient("stores")
public interface StoreClient {
//添加调用路径,具体需要调用那个方法
@RequestMapping(method = RequestMethod.GET, value = "/stores")
List getStores();
@RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
Store update(@PathVariable("storeId") Long storeId, Store store);
}
在上面@FeignClient注解中,(“stores”)是一个任意客户端名称,用于创建Ribbon负载均衡器, 您还可以使用url属性指定URL(绝对值或仅指定主机名)。 应用程序上下文中bean的名称是接口的完全限定名称。 要指定自己的别名值,可以使用限定符@FeignClient注释的值。
上面的Ribbon客户端将要发现“stores”服务的物理地址。 如果您的应用程序是Eureka客户端,那么它将解析Eureka服务注册表中的服务(从注册中心获取具体的"stores"服务调用地址)。 如果您不想使用Eureka,则只需在外部配置中配置服务器列表即可
Spring Cloud的Feign支持的核心概念是指定客户端的概念。 每个feign客户端都是一组组件的一部分,这些组件一起工作以按需联系远程服务器,并且该集合具有一个名称,您可以使用@FeignClient注释将其作为应用程序开发人员提供。 Spring Cloud根据需要为每个命名客户端创建一个新的集合作为ApplicationContext FeignClientsConfiguration。 这包含(除其他外)feign.Decoder,feign.Encoder和feign.Contract。【Feign的默认配置是FeignClientsConfiguration,该类定义了Feign默认使用的编码器、解码器、所有使用的契约】
Spring Cloud允许您通过使用@FeignClient的configuration属性自定义Feign的配置,自定义的优先级会比默认的FeignClientsConfiguration优先极高。
例如:
//FooConfiguration 自定义配置
@FeignClient(name = "stores", configuration = FooConfiguration.class)
public interface StoreClient {
//..
}
注意:
FooConfiguration不需要使用@Configuration注释。 但是,如果是,则注意将其从任何包含此配置的@ComponentScan中排除,因为该配置会被所有@FeignClient共享。 这可以通过将它放在来自任何@ComponentScan或@SpringBootApplication的单独的非重叠包中来避免,或者可以在@ComponentScan中明确排除它
在@FeignClient中推荐使用name属性,serviceId属性已经过期不推荐了。
以前可能使用url属性,写具体调用服务的物理地址,现在只需写name属性填写具体的服务名称,将会自动解析。
@FeignClient注解中还支持name和url属性值得占位符。
@FeignClient(name = "${feign.name}", url = "${feign.url}")
public interface StoreClient {
//..
}
spring Cloud Netflix默认为feign(BeanType beanName:ClassName)提供以下bean:
创建其中一种类型的bean并将其放在@FeignClient配置中(例如下面的FooConfiguration)允许您覆盖默认。
@Configuration
public class FooConfiguration {
@Bean
public Contract feignContract() {
return new feign.Contract.Default();
}
@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("user", "password");
}
}
上面讲使用feign原生的默认契约去掉springmvc,这样就可以使用feign自带的注解了。而且配置基于用户认证,只有通过认证才能调用。
@FeignClient相关配置还可通过配置文件配置
如果您更喜欢使用配置属性来配置所有@FeignClient,则可以使用默认的Feign name创建配置属性。
如果同时创建@Configuration bean和属性配置文件,则配置属性优先级高。 它将覆盖@Configuration值。 但是,如果要将优先级更改为@Configuration,则可以将feign.client.default-to-properties更改为false。
注意:
如果你需要使用ThreadLocal绑定变量,需要进行如下设置。
在feign调用中禁用断路器和膝盖修改线程隔离策略。
如果Hystrix在类路径上并且feign.hystrix.enabled = true,则Feign将使用断路器包装所有方法(这是一个全局的配置).
如果不想设置全局的关闭hystrix,而只是针对某个服务关闭Hystrix需要如下配置:
@Configuration
public class FooConfiguration {
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
return Feign.builder();
}
}
Hystrix支持回退的概念:在电路打开或出现错误时执行的默认代码路径。 要为给定的@FeignClient启用回退,请将fallback属性设置为实现回退的类名。 您还需要将实现声明为Spring bean。
实例代码:
@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 {
@Override
public HystrixClient create(Throwable cause) {
return new HystrixClient() {
@Override
public Hello iFailSometimes() {
return new Hello("fallback; reason was: " + cause.getMessage());
}
};
}
}
在Feign使用Hystrix做服务降级时,ApplicationContext中有多个相同类型的bean。 这将导致@Autowired无法工作,因为没有一个bean或一个标记为primary的bean。 为了解决这个问题,Spring Cloud Netflix将所有Feign实例标记为@Primary,因此Spring Framework将知道要注入哪个bean。 在某些情况下,这可能并不理想。 要关闭此行为,请将@FeignClient的主要属性设置为false。
@FeignClient(name = "hello", primary = false)
public interface HelloClient {
// methods here
}
Feign支持单接口继承,这样可以将常用的进行接口封装。
列如:
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请求启用请求或响应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日志记录仅响应DEBUG级别。
application.yml.
logging.level.project.user.UserClient: DEBUG
您可以为每个客户端配置的Logger.Level对象告诉Feign记录日志级别,支持四种日志级别:
例如配置打印所有日志,设置Logger.Level 为FULL
@Configuration
public class FooConfiguration {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
微信公众号:
JAVA程序猿成长之路
分享资源,记录程序猿成长点滴。专注于Java,Spring,SpringBoot,SpringCloud,分布式,微服务。