使用Feign代替RestTemplet
Feign
RestTemplet存在的问题
String url = "http: //userservice/user/" + order.getUserId();
User user = restTemplate.getFor0bject(url, User.class);
- 可读性差
- 参数复杂
- URL难以维护
Feign声明式的Http客户端,官方地址:https://github.com/OpenFeign/feign
使用案例
- 引入坐标
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 在需要发起请求的服务的启动类添加注解开启Feign的功能
@EnableFeignClients
- 编写Feign客户端
@FeignClient("userservice") //指明服务名称
public interface UserClient {
@GetMapping("/user/{id}") //请求类型和请求路径
User findById(@PathVariable("id") Long id); //返回值与请求参数
}
- 使用声明出的方法代替原始的RestTemplate
@Autowired
private UserClient userClient;
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
/*
String url = "http://userservice/user/" + order.getUserId();
//使用RestTemplate发送请求
User user = restTemplate.getForObject(url, User.class);
*/
User user = userClient.getUser(order.getUserId());
order.setUser(user);
// 4.返回
return order;
}
可以发现简化很多,并且代码十分美观
Feigen的自定义配置
配置项 | 描述 | 说明 |
---|---|---|
feign.Logger.Level | 修改日志级别 | NONE 、BASIC 、HEADERS 、FULL |
feign.codec.Decoder | 响应结果的解析器 | 默认解析 JSON 字符串为 Java 对象,可自定义解析器 |
feign.codec.Encoder | 请求参数编码 | 默认将请求参数编码为 HTTP 请求格式,可自定义编码器 |
feign.Contract | 支持的注解格式 | 默认支持 SpringMVC 注解,可自定义注解格式 |
feign.Retryer | 失败重试机制 | 默认无重试机制(但会使用 Ribbon 的重试),可自定义重试策略 |
一般只需要配置日志级别
配置文件写法:
#全局生效:
feign:
client:
config:
default: #这里配置全局生效
loggerLevel: FULL
# 或者
userservice: #这里配置局部生效
loggerLevel: full
通过配置类来配置Feign
//声明一个类,并且在其中声明一个Bean
public class FeignClientConfigurationP{
@Bean
public Logger.Level feignLogLevel(){
return Logger.Level.BASIC;
}
}
/*
如果是全局配置,则吧它放到@EnableFeignClients这个注解中(启动类上)
@EnableFeignclients(defaultConfiguration = FeignclientConfiguration.class)
如果是局部配置,则把它放到@FeignClient这个配置类中(配置类上)
@FeignClient(value = "userservice", configuration = FeignClientConfiguration.class)
*/
性能优化
Feign底层客户端实现
- URLConnection:默认实现,不支持连接池
- Apache Httpclient :支持连接池
- OKHttp:支持连接池
因此优化Feign的性能主要包括:
- 使用连接池代替默认的URLConnection
- 日志级别,使用basic或none
此处以添加HttpClient的支持举例
- 导坐标
<dependency>
<groupid>io.github. openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
- 配置连接池
feign:
client:
config:
default: #default全局的配置
loggerLevel: BASIC #日志级别,BASIC就是基本的请求和响应信息
httpclient:
enabled: true #开启feign对HttpClient的支持
max-connections: 200 #最大的连接数
max-connections-per-route: 50 #每个路径的最大连接数
实际项目中的使用方式
将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块当中提供给消费者使用。
- 创建一个feign-api的module,引入feign的依赖
- 将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中
- 在order-service中引入feign-api的依赖
- 修改order-service中的所有与上述三个组件有关的import部分,改成导入feign-api中的包
修改后存在的问题:自定义的FeignClient不再SpringBootApplication扫描包范围时,有两种解决方法:
1.指定FeignClient所在包
@EnableFeignClients(basePackages = 'cn.itcast.feign.clients')
2.指定FeignClient字节码 //更推荐
@EnableFeignClients(clients = {UserClient.class})