Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务一样简单, 只需要创建一个接口并添加一个注解即可。
引入依赖
<!-- SpringCloud Openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
default: 需要超时控制的服务名称,如果是default则对所有服务都生效
connectTimeout: 建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
readTimeout: 建立连接后从服务器读取到可用资源所用的时间
服务消费方启动类添加@EnableFeignClients()开启,可以指定basePackages feign API包路径
远程调用API
/**
* 用户工单服务
*/
@FeignClient(contextId = "remoteOrderApi", value = ServiceNameConstants.ORDER_SERVICE_NAME, fallbackFactory = RemoteOrderApiFallbackFactory.class)
public interface RemoteOrderApi {
@GetMapping("/order/info/get/{id}")
OrderInfo getById(@PathVariable("id") Integer id);
}
远程调用
@RestController
@RequestMapping("/user")
public class UserOrderController {
@Autowired
private RemoteOrderApi remoteOrderApi;
@GetMapping("/getOrder/{orderId}")
public OrderInfo getOrderByOrderId(@PathVariable("orderId")Integer orderId){
return remoteOrderApi.getById(orderId);
}
}
服务器提供方
/ 动态刷新配置
@RefreshScope
@RestController
@RequestMapping("/order/info")
public class OrderInfoController {
@Autowired
private OrderInfoService orderInfoService;
@RequestMapping("/save")
public Integer saveOrderInfo(){
OrderInfo orderInfo = new OrderInfo();
orderInfo.setOrderNum("12345");
orderInfo.setUserId(1);
orderInfo.setCreateTime(new Date());
return orderInfoService.saveOrderInfo(orderInfo);
}
@GetMapping("/get/{id}")
public OrderInfo getById(@PathVariable("id") Integer id,HttpServletRequest request){
System.out.println(request.getHeader("testToken"));
return orderInfoService.getById(id);
}
}
服务降级处理回调
/**
* 工单服务降级处理
*/
@Component
public class RemoteOrderApiFallbackFactory implements FallbackFactory<RemoteOrderApi> {
private static final Logger log = LoggerFactory.getLogger(RemoteOrderApiFallbackFactory.class);
@Override
public RemoteOrderApi create(Throwable cause) {
return new RemoteOrderApi() {
@Override
public OrderInfo getById(Integer id) {
return new OrderInfo();
}
};
}
}
要使用服务降级处理要添加Sentinel 依赖,并且在配置中开启feign.sentinel.enabled=true,这样在服务提供方出现报错或者宕机,就会走RemoteOrderApiFallbackFactory
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
1、统一添加 header 信息;
2、对 body 中的信息做修改或替换;
/**
* Feign 配置注册
*/
@Configuration
public class FeignAutoConfiguration {
/**
* 注册使用自定义feign拦截器
*/
@Bean
public RequestInterceptor requestInterceptor(){
return new FeignRequestInterceptor();
}
/**
* 日志级别
* 通过源码可以看到日志等级有 4 种,分别是:
* NONE:不输出日志。
* BASIC:只输出请求方法的 URL 和响应的状态码以及接口执行的时间。
* HEADERS:将 BASIC 信息和请求头信息输出。
* FULL:输出完整的请求信息。
*/
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
/**
* Feign请求拦截器
*/
@Component
public class FeignRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
//测试
String testToken = UUID.randomUUID().toString();
requestTemplate.header("testToken",testToken);
}
}
在微服务中可以用 @Import({FeignAutoConfiguration.class}) 把feign配置添加到spring容器