目录
什么是Feign
Feign是Netflix开发的声明式,模板化的http客户端,可以帮助我们更加便捷、优雅的调用HTTP API。
Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等
SpringCloud OpenFeign对Feign进行了增强,使其支持SpringMvc注解,另外还整合了Ribbon和Nacos,从而使得Feign的使用更加方便。
优势:Feign可以做到使用Http请求远程服务时就像调本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个http请求,它就像Dubbo一样,自定义直接调用接口方法调用提供者,而不需要通过常规的httpClient构造请求在解析返回数据,他解决了开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。
SpringCloudAlibaba整合OpenFeign
1.引入依赖
<!--添加openfeign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.编写调用接口+@FeignClient注解
package com.zjb.order.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* name: 指定调用rest接口所对应的服务名
* path:指定调用rest接口所在的Controller指定的RequestMapping
*/
@FeignClient(name = "stock-service",path = "/stock")
public interface StockFeignSerivce {
/**
* 声明需要调用的rest接口对应的方法
* @return
*/
@RequestMapping("/reduct")
String reduct();
}
3.调用端在启动类上添加@EnableFeignClients注解
package com.zjb.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
4.发起调用,像调用本地方式一样调用远程服务
package com.zjb.order.controller;
import com.zjb.order.feign.StockFeignSerivce;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private StockFeignSerivce stockFeignSerivce;
@RequestMapping("/add")
public String add(){
System.out.println("---下单---");
String msg = stockFeignSerivce.reduct();
System.out.println("调用库存服务:"+msg);
return "下单成功";
}
}
OpenFeign自定义配置
日志配置
有时候我们遇到bug,比如调用接口失败,参数没收到等问题,就需要配置feign的日志了,以此让feign把请求信息输出出来。
1、定义一个配置类,指定日志级别
package com.zjb.order.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Feign日志配置
* 全局配置:当使用@Configuration会将配置作用在所有的服务提供方
* 局部配置:如果只想针对某一个服务进行配置,就不要加@Configuration
*/
@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
也可以在yml文件中配置全局配置
feign:
client:
config:
loggerLevel: FULL
通过源码可以看到日志等级有4种,分别是:
- NONE【性能最佳,适用于生产】不记录任何日志,(默认值)
- BASIC【适用于生产环境追踪问题】仅记录请求方法,URL,响应状态代码以及执行时间
- HEADERS:记录BASIC的基础上,记录请求和响应的header
- FULL 【比较适用于开发及测试环境定位问题】记录请求和响应的header,body和元数据
2、局部配置,让调用的微服务生效,在@FeignClient注解中指定使用的配置类
package com.zjb.order.feign;
import com.zjb.order.config.FeignConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* name: 指定调用rest接口所对应的服务名
* path:指定调用rest接口所在的Controller指定的RequestMapping
*/
@FeignClient(name = "stock-service",path = "/stock",configuration = FeignConfig.class)
public interface StockFeignSerivce {
/**
* 声明需要调用的rest接口对应的方法
* @return
*/
@RequestMapping("/reduct")
String reduct();
}
局部配置还可以在yml文件中进行配置
feign:
client:
config:
stock-service: #对应服务名
loggerLevel: FULL
3、在yml配置文件中执行client的日志级别才能正常输出日志,格式是"logging.level.feign接口包路径=debug"
#SpringBoot默认的日志级别是info,feign的debug日志级别就不会输出
logging:
level:
com.zjb.order.feign: debug
超时时间配置
通过Options可以配置连接超时时间和读取超时时间,Options的第一个参数是连接的超时时间(ms),默认值是2s,第二个参数是请求处理的超时时间(ms),默认是5s
全局配置
配置类
@Bean
public Request.Options options(){
return new Request.Options(5000,10000);
}
yml中配置
feign:
client:
config:
#连接超时时间,默认2s
connectTimeout: 5000
#读取超时时间,默认5s
readTimeout: 10000
局部配置
feign:
client:
config:
stock-service: #对应服务名
#连接超时时间,默认2s
connectTimeout: 5000
#读取超时时间,默认5s
readTimeout: 10000
自定义拦截器
1.添加拦截器配置类,并实现RequestInterceptor接口
package com.zjb.order.interceptor.feign;
import feign.RequestInterceptor;
import feign.RequestTemplate;
/**
* feign 自定义拦截器
*/
public class DiyFeignInterceptor implements RequestInterceptor {
public void apply(RequestTemplate requestTemplate) {
//todo 业务逻辑
}
}
2. 把自定义的拦截器注入到Spring容器中
@Bean
public DiyFeignInterceptor diyFeignInterceptor(){
return new DiyFeignInterceptor();
}
也可以在yml文件中进行配置
feign:
client:
config:
requestInterceptors[0]: com.zjb.order.interceptor.feign.DiyFeignInterceptor