1、什么是 Feign ?

Feign是 Netflix 公司开发的声明式、轻量级Restful的HTTP服务客户端,内置了Ribbon,用于客户端负载均衡。

OpenFeign 是 Spring Cloud 在 Feign 的基础上支持了SpringMVC的注解,如@RequesMapping等等。

在之前我们学习了注册中心,将服务注册到注册中心,然后通过 RestTemplate 类去调用服务,但是在调用服务时,我们需要拼接服务的地址和参数等信息。为了简化这个步骤,我们就需要使用 Feign 。

在这里插入图片描述

2、使用 OpenFeign

想要在项目中使用 OpenFeign ,我们必须完成如下几个步骤:

  • 在项目中导入所需依赖:

    <dependency>
    	 <groupId>org.springframework.cloud</groupId>
    	 <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  • 创建一个Feign接口:此接口是在Feign中调用微服务的核心接口,需要使用@FeignClient注解,一般一个接口对应一个服务。

    @Component
    @FeignClient(name="需要调用的服务在注册中心的服务名称") 
    public interface ProductFeginClient { 
    
    	//具体调用的请求路径 
    	@RequestMapping(value = "/product/{id}",method = RequestMethod.GET) 
    	public Product findById(@PathVariable("id") Long id);
    }
    
  • 修改启动类:在启动类上添加@EnableFeignClients注解;

    @SpringBootApplication
    @EnableFeignClients
    public class EurekaClientApplication{
    //省略....
    //删除 关于对 restTemplate 的注入,因为不再直接使用 restTemplate 对象
    }
    
  • 修改服务调用

    @RestController 
    @RequestMapping("/order") 
    public class OrderController {
        //不再直接使用 restTemplate 对象进行调用
     	//@Autowired
    	//private RestTemplate restTemplate;
    
    	@Autowired 
    	private ProductFeginClient productFeginClient; 
    
    	@GetMapping("/buy/{id}") 
    	public Product order(@PathVariable Long id) { 
    	return productFeginClient.findById(id); 
    	} 
    }
    

在使用了 OpenFeign 之后的访问流程是:

  • 浏览器访问localhost/order/buy/1
  • 调用 OrderController 类中的 order 方法
  • order 方法再调用 ProductFeginClient 接口的 findById 类
  • findById 类在去通过 OpenFeign 调用其他的服务

3、Feign 的相关配置

在使用 Feign 时,可以添加一些配置对 Feign 进行配置。

feign: 
	compression: 
		request: 
			enabled: true # 开启请求压缩 
			mime-types: text/html,application/xml,application/json # 设置压缩的数据类型 	
			min-request-size: 2048 # 设置触发压缩的大小下限
		response: 
			enabled: true # 开启响应压缩
	client: 
		config: 
			Name: #具体的feign接口名称
				connectTimeout: 5000 
				readTimeout: 5000
				# 配置Feign的日志级别,相当于代码配置方式中的Logger 
				loggerLevel: full 
				# Feign的错误解码器,相当于代码配置方式中的
				ErrorDecoder errorDecoder: com.example.SimpleErrorDecoder
				# 配置重试,相当于代码配置方式中的
				Retryer retryer: com.example.SimpleRetryer 
				# 配置拦截器,相当于代码配置方式中的
				RequestInterceptor requestInterceptors: 
					- com.example.FooRequestInterceptor 
					- com.example.BarRequestInterceptor 
				decode404: false
logging: 
	level: 
		feign接口的全限定名: debug
  • Feign 支持对请求和响应进行压缩,以减少通信过程中的性能损耗。通过配置项中的compression可以开启压缩功能。

    feign: 
    compression: 
    	request: 
    		enabled: true # 开启请求压缩 
    		mime-types: text/html,application/xml,application/json # 设置压缩的数据类型 	
    		min-request-size: 2048 # 设置触发压缩的大小下限
    	response: 
    		enabled: true # 开启响应压缩
    
  • 在开发阶段往往希望看到 Feign 请求过程的日志记录,在默认情况下 Feign 的日志是没有开启的。所以想要开启日志,通过下列配置对具体的Feign 接口进行设置。

    feign: 
    	client: 
    		config: 
    			Name: #具体的feign接口名称
    				loggerLevel: full 
    logging: 
    	level: 
    		feign接口的全限定名: debug
    

    logging: level: feign接口的全限定名: debug Feign日志只会对日志级别为debug的做出响应

    loggerLevel有四个属性值,NONE(不记录任何日志(默认值))BASIC(仅记录请求方法、URL、响应状态代码以及执行时间)HEADERS(在BASIC基础上,记录请求和响应的header)FULL(记录请求和响应的header、body和元数据)

4、@EnableFeignClients 和 @FeignClient

在使用 Feign 的过程中,我们使用了两个注解@EnableFeignClients@FeignClient,下面我们对着两个注解进行分析。

@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.TYPE}) 
@Documented 
@Import({FeignClientsRegistrar.class}) 
public @interface EnableFeignClients {

}

@EnableFeignClients注解的声明中可以看出,注解中引入了 FeignClientsRegistrar 类:

class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
//......
}

这个类实现了 ImportBeanDefinitionRegistrar 接口,所以在类中有一个 registerBeanDefinitions() 方法:

public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
    this.registerDefaultConfiguration(metadata, registry);
    this.registerFeignClients(metadata, registry);
}

这个 registerBeanDefinitions() 方法主要用于解析和注册BeanDefinition,注册的对象类型有两种:

  • 注册配置的配置信息
  • 注册那些添加了 @FeignClient注解的类或接口
public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
//......
}

上述这个方法就是 registerBeanDefinitions() 方法中调用的那个方法。这个方法主要用于扫描整个工程下面的被 @FeignClient注解声明的类或接口,然后对这些类进行初始化配置。最后会调用 registerBeanDefinition() 方法完成注册。

private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
}
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐