SpringCloud整合声明式HTTP客户端-Feign
文章目录
- 一、Feign介绍
- 1. 什么是Feign?
- 2. Feign组件:
- 二、基于Feign实现微服务远程调用
- 2.1. 引入feign依赖
- 2.2. 启动类加@EnableFeignClients注解
- 2.3. 添加属性配置(暂无)
- 2.4. 创建一个feign接口类
- 2.5. 修改Ribbon调用Feign方式
- 2.5.1. Feign调用方式
- 2.5.2. 以前Ribbon调用方式
- 2.6. 验证
- 2.6.1. 启动nacos注册中心
- 2.6.2. 启动user-center应用
- 2.6.3. 启动content-center应用
- 2.6.4. 浏览器访问
- 三、细粒度自定义配置
- 3. 自定义Feign日志级别
- 3.1. java代码配置方式
- 3.1.1. 创建feign配置类
- 3.1.2. 在feign接口类上指定feign的配置类
- 3.1.4. 添加监听feign接口的打印体日志
- 3.1.5. 验证
- 3.2. 属性配置方式
- 3.2.1 添加配置信息
- 3.2.2 重启content-center应用
- 四、 全局配置自定义
- 4.1. java代码方式(全局)
- 4.1.1 在启动类上添加注解
- 4.1.2 feign配置类
- 4.1.3 重启content-center应用
- 4.2. 配置属性方式(全局)
- 4.2.1 启动类
- 4.2.2 配置文件属性
- 4.2.3 重启content-center应用
- 五、 feign支持的配置项
- 5.1. 代码方式
- 5.2. 属性配置方式:
- 六、 配置最佳实践总结
- 6.1. Ribbon配置vs Feign配置
- 6.2. Feign代码方式vs属性方式
- 6.3. 配置优先级:
- 七、 最佳实践:
一、Feign介绍
1. 什么是Feign?
Feign是Netfix开源的声明式HTTP客户端
Github地址:https://github.com/openfeign/feign
2. Feign组件:
接口 | 作用 | 默认值 |
---|---|---|
Feign.Builder | Feign的入口 | Feign.Builder |
Client | Feign底层用默认去请求 | 和Ribbon配合时:LoadBalancerFeignClient;不和Ribbon配合时feign.Client.default |
Contract | 契约,注解支持 | SpringMvcContract |
Encoder | 编码器,用于将对象转换成http请求消息体 | SpringEncoder |
Decoder | 解码器,将相应消息体转换成对象 | ResponseEntityDecoder |
Logger | 日志管理器 | Slf4jLogger |
RequestInterceptor | 用于为每个请求添加通用逻辑 | 无 |
二、基于Feign实现微服务远程调用
2.1. 引入feign依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
2.2. 启动类加@EnableFeignClients注解
//扫描mybatis那些包里面的接口
@SpringBootApplication
@MapperScan("com.itmuch")
@EnableFeignClients
public class ContentCenterApplication {public static void main(String[] args) {SpringApplication.run(ContentCenterApplication.class, args);}
}
2.3. 添加属性配置(暂无)
2.4. 创建一个feign接口类
//@FeignClient(name = "应用名称")
@FeignClient(name = "user-center")
public interface UserCenterFeignClient {/*** http://localhost:8082/users/{id}* @param id* @return*/@GetMapping("/users/{id}")UserDTO finById(@PathVariable Integer id);
}
2.5. 修改Ribbon调用Feign方式
2.5.1. Feign调用方式
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ShareServiceImpl implements IShareService {private final ShareMapper shareMapper;private final UserCenterFeignClient userCenterFeignClient;@Overridepublic ShareDTO findById(Integer id) {//获取分享详情Share share = this.shareMapper.selectByPrimaryKey(id);//发布人idInteger userId = share.getUserId();//怎么调用用户微服务的/users/{userId}呢?
// Feign重构后UserDTO userDTO = userCenterFeignClient.finById(userId);//消息的装配ShareDTO shareDTO = new ShareDTO();BeanUtils.copyProperties(share, shareDTO);shareDTO.setWxNickname(userDTO.getWxNickname());return shareDTO;}
}
2.5.2. 以前Ribbon调用方式
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ShareServiceImpl implements IShareService {private final ShareMapper shareMapper;private final RestTemplate restTemplate;@Overridepublic ShareDTO findById(Integer id) {//获取分享详情Share share = this.shareMapper.selectByPrimaryKey(id);//发布人idInteger userId = share.getUserId();//怎么调用用户微服务的/users/{userId}呢?//Ribbo重构后UserDTO userDTO = this.restTemplate.getForObject("http://user-center/users/{userId}", UserDTO.class, userId);//消息的装配ShareDTO shareDTO = new ShareDTO();BeanUtils.copyProperties(share, shareDTO);shareDTO.setWxNickname(userDTO.getWxNickname());return shareDTO;}
2.6. 验证
2.6.1. 启动nacos注册中心
2.6.2. 启动user-center应用
2.6.3. 启动content-center应用
2.6.4. 浏览器访问
访问:http://localhost:8082/shares/2
三、细粒度自定义配置
3. 自定义Feign日志级别
级别 | 打印内容 |
---|---|
NONE(默认值) | 不记录任何日志 |
BASIC | 请求方法、URL、响应状态码以及执行时间 |
HEADERS | 记录BASIC级别的基础上,记录请求和相应的header |
FULL | 记录请求响应的header、body和元数据 |
3.1. java代码配置方式
3.1.1. 创建feign配置类
/*** feign的配置类* 这个类别加@Configuration注解,* 否则必须挪到@ComponentScan能扫描的包以外*/
public class UserCenterFeignConfiguration {@Beanpublic Logger.Level level(){
// 让feign打印所有的请求细节return Logger.Level.FULL;}
}
3.1.2. 在feign接口类上指定feign的配置类
@FeignClient(name = "user-center",configuration = UserCenterFeignConfiguration.class)
public interface UserCenterFeignClient {/*** http://localhost:8082/users/{id}* @param id* @return*/@GetMapping("/users/{id}")UserDTO finById(@PathVariable Integer id);
}
3.1.4. 添加监听feign接口的打印体日志
logging:level:com.itmuch.contentcenter.feignclient.UserCenterFeignClient: debug
3.1.5. 验证
访问:http://localhost:8082/shares/2
3.2. 属性配置方式
3.2.1 添加配置信息
- feign接口:
@FeignClient(name = "user-center")
public interface UserCenterFeignClient {/*** http://localhost:8082/users/{id}* @param id* @return*/@GetMapping("/users/{id}")UserDTO finById(@PathVariable Integer id);
}
- application.yml添加配置信息
##监听feign接口的日志
logging:level:com.itmuch.contentcenter.feignclient.UserCenterFeignClient: debug
#feign 细粒度日志级别属性配置形式
feign:client:config:user-center: #想要调用微服务的应用名称loggerLevel: full
3.2.2 重启content-center应用
访问:http://localhost:8082/shares/2
四、 全局配置自定义
4.1. java代码方式(全局)
4.1.1 在启动类上添加注解
@EnableFeignClients(defaultConfiguration = GlobalFeignConfiguration.class)
defaultConfiguration 指向feign的配置类即可
//扫描mybatis那些包里面的接口
@SpringBootApplication
@MapperScan("com.itmuch")
@EnableFeignClients(defaultConfiguration = GlobalFeignConfiguration.class)
public class ContentCenterApplication {public static void main(String[] args) {SpringApplication.run(ContentCenterApplication.class, args);}}
4.1.2 feign配置类
/*** feign的配置类* 这个类别加@Configuration注解,* 否则必须挪到@ComponentScan能扫描的包以外*/
public class GlobalFeignConfiguration {@Beanpublic Logger.Level level(){
// 让feign打印所有的请求细节return Logger.Level.FULL;}
}
4.1.3 重启content-center应用
访问:http://localhost:8082/shares/2
4.2. 配置属性方式(全局)
4.2.1 启动类
@SpringBootApplication
@MapperScan("com.itmuch")
@EnableFeignClients
public class ContentCenterApplication {public static void main(String[] args) {SpringApplication.run(ContentCenterApplication.class, args);}
4.2.2 配置文件属性
##监听feign接口的日志
logging:level:com.itmuch.contentcenter.feignclient.UserCenterFeignClient: debug
#feign 全局日志级别属性配置形式
feign:client:config:default:loggerLevel: full
4.2.3 重启content-center应用
访问:http://localhost:8082/shares/2
五、 feign支持的配置项
5.1. 代码方式
配置项 | 作用 |
---|---|
Logger.level | 置顶日志级别 |
Retryer | 指定充实策略 |
ErrorDecoder | 指定错误解码器 |
Request.Options | 超时时间 |
Conection<Requestinterception> | 拦截器 |
SetterFactory | 用于设置Hystrix的配置属性,Feign整合Hystrix才会用 |
5.2. 属性配置方式:
feign:client:config:<feignName>:connectTimeout: 5000 #连接超时时间readdTimeout: 5000 #连接超时时间loggerLevel: fullerrorDecoder: com.example.SimpleErrorDecoder #错误解码器retryer: com.example.SimpleRetryer #重试策略requestInterceptors:- com.example.FooRequestInterceptor #拦截器#是否对404错误码解码#处理逻辑详见feign.SynchronousMethodHander #executeAndDecodedecode404: falseencoder: com.example.SimpleEncoder #编码器decoder: com.example.SimpleDecoder #解码器contract: com.example.SimpleContract #契约
六、 配置最佳实践总结
6.1. Ribbon配置vs Feign配置
方式 | 粒度 | Ribbon | Feign |
---|---|---|---|
代码 | 局部 | @RibbonClient(Configuration=xx.class) X必须加@Configuration且必须放在父子上下文无法扫描的包 | @FenginClient(configuration=Y.class) Y的@Configuration可选,如果有,不许放在父子上下文无法扫描的包即可 |
方式 | 全局 | @RibbonClients(defaultConfiguration) | @EnableFeignClients//(defaultConfiguration = GlobalFeignConfiguration.class) |
属性 | 局部 | .ribbon.NFLoadBalancerClassName | feign.client.config..loggerLevel |
方式 | 全局 | feign.client.config.default.loggerLevel |
6.2. Feign代码方式vs属性方式
配置方式 | 优点 | 缺点 |
---|---|---|
代码配置 | 基于代码灵活 | 如果Feign的配置类加了@Configuration注解需要注意父子上下文,线上修改需要重新打包、发布 |
属性配置 | 易上手,配置更加直观,线上修改不需要重新打包、发布优先级更高 | 极端场景下没有代码配置灵活 |
6.3. 配置优先级:
全局代码<全局属性<细粒度代码<细粒度属性
七、 最佳实践:
尽量使用属性配置,属性配置实现不了了的阿情况下在考虑用代码配置
在同一个微服务内尽量保持单一性,比如同一使用属性配置,不要两种方式混用,增加定位代码的复杂性