回顾最初我们为了实现跨服务调用时,在不使用Dubbo这种RPC协议时,我们借助了RestTemplate对象实现跨服务调用,为了解决跨服务调用时调用地址写死的问题我们又引入了注册中心,从而实现根据服务名的调用。但是回过头来查看我们这段调用方法,依然存在服务地址硬编码、代码阅读性差的问题。
// 2.1 拼接请求用户中心的地址
String url = "http://userservice/user/" + userId;
// 2.2 请求用户中心
return restTemplate.getForObject(url, User.class);
那么就没有更优雅的HTTP协议跨服务调用解决方案吗?本章节Feign就是解决我们上述问题的方案之一。
1 Feign替代RestTemplate
1.依赖引入
在order-service中引入feign依赖
org.springframework.cloud
spring-cloud-starter-openfeign
2.添加注解
在order-service启动类添加注解,开启Feign功能:
3.编写Feign客户端
在order-service中新建接口,内容如下:
package cn.itcast.order.client;
import cn.itcast.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient("userservice")
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
此客户端作用是基于SpringMVC的注解来声明远程调用的信息,Feign就可以发送http请求,如:
● 服务名称:userservice
● 请求方式:GET
● 请求路径:/user/{id}
● 请求参数:Long id
● 返回值类型:User
4.测试
修改order-service中OrderService类中的queryOrderById方法,使用Feign客户端代替RestTemplate:
2.自定义配置
Feign可以支持多种自定义配置,总结如下
类型 作用 说明
feign.Logger.Level 修改日志级别 包含四种不同的级别:NONE、BASIC、HEADERS、FULL
feign.codec.Decoder 响应结果的解析器
http远程调用的结果做解析,例如解析json字符串为java对象
feign.codec.Encoder 请求参数编码 将请求参数编码,便于通过http请求发送
feign. Contract 支持的注解格式 默认是SpringMVC的注解
feign. Retryer 失败重试机制 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试
一般情况下默认值即可满足使用,如需自定义只需创建自定义的@Bean覆盖默认即可,以日志级别为例:
1.配置文件修改
基于配置文件修改Feign的日志级别可以针对单个服务:
feign:
client:
config:
userservice: # 针对某个微服务的配置
loggerLevel: FULL # 日志级别
也可以针对全部服务:
feign:
client:
config:
default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
loggerLevel: FULL # 日志级别
日志的级别分为四种:
● NONE:不记录任何日志信息,这是默认值。
● BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
● HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
● FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据
2.Java代码修改
除了配置文件类型,也可通过Java代码创建自定义Bean来覆盖默认Bean即可,对应此处即声明一个Logger.Level的对象:
package cn.itcast.order.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
/**
- @author 何波
- @version 1.0.0
- @desc 自定义日志级别
@since 2023/1/10 16:36
*/
public class DefaultFeignConfiguration {@Bean
public Logger.Level feignLogLevel(){return Logger.Level.BASIC; // 日志级别为BASIC}
}
如果想全局生效,将其放在启动类的@EnableFeignClients注解中:
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)
如果想局部生效,则将其放在对应@FeignClient这个注解中:
@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)
3.Feign使用优化