Spring Cloud OpenFeign使用教程
文章目录
Spring Cloud OpenFeign Demo
之前项目中需要在Spring Cloud中使用OpenFeign的情况,Spring Cloud的版本是目前最新的Greenwich.SR2版本,对应的Spring boot是2.1.7.RELEASE。
在网上找了很多资料,大多言之不详,并且版本也比较低,不适合我的最新版本Spring Cloud的需求。 所以决定还是自己写个教程。
本教程要解决如下几个问题:
- 怎么配置OpenFeignServer
- 怎么配置OpenFeignClient
- 多个参数传递问题
- FeignClient的日志问题
- 多个FeignClient使用同一个name的问题
怎么配置OpenFeignServer
我们知道OpenFeign是用在Spring Cloud中的声明式的web service client。
OpenFeignServer就是一个普通的Rest服务,不同的是我们需要将他注册到eureka server上面,方便后面的OpenFeignClient调用。
启动类如下:
@SpringBootApplication
@EnableDiscoveryClient
public class OpenFeignServer {
public static void main(String[] args) {
SpringApplication.run(OpenFeignServer.class, args);
}
}
我们定义了两个Rest服务:
OrderController:
@Slf4j
@RestController
@RequestMapping(path = "/order")
public class OrderController {
/**
* PostMapping with @RequestBody
* @param user
*/
@PostMapping("doOrder")
public void doOrder(@RequestBody User user){
log.info("do order !!!!");
}
}
UserController:
@RestController
@RequestMapping(path = "/user")
public class UserController {
/**
* GetMapping example with @RequestParam
* @param userId
* @return userName
*/
@GetMapping("getUserName")
public String getUserName(@RequestParam("userId") String userId){
if("100".equals(userId)) {
return "张学友";
}else{
return "刘德华";
}
}
/**
* GetMapping example with @RequestParam and @SpringQueryMap
* @param userId
* @param user
* @return userAge
*/
@GetMapping("getUserAge")
public String getUserAge(@RequestParam("userId") String userId, @SpringQueryMap User user){
if("100".equals(userId)) {
return "20";
}else{
return "18";
}
}
}
我们将其注册到eureka上面,名字为openfeign-server
spring:
application:
name: openfeign-server
怎么配置OpenFeignClient
OpenFeignClient的pom依赖如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
配置OpenFeignClient只需要使用@FeignClient来注解一个interface即可,如下所示:
@FeignClient(value = "openfeign-server")
@RequestMapping(path = "/user")
public interface UserClient {
@GetMapping("getUserName")
public String getUserName(@RequestParam("userId") String userId);
@GetMapping("getUserAge")
public String getUserAge(@RequestParam("userId") String userId, @SpringQueryMap User user);
}
其中@FeignClient中的value是要调用的服务的注册名,即OpenFeignServer在eureka的注册名。
FeignClient的 Request路径,方式和参数要和被调用的Rest服务保持一致。
这样我们就可以像下面一样来调用OpenFeignClient了:
@Slf4j
@RestController
public class UserController {
@Autowired
private UserClient userClient;
@GetMapping("getUserName2")
public void getUserName(){
log.info(userClient.getUserName("100"));
}
}
多个参数传递问题
一般我们会使用@GetMapping和@PostMapping两种方式来调用Rest服务。
而接收的参数则会使用@RequestParam和@RequestBody来获取。
首先我们讲一下@RequestBody,@RequestBody只能用在Post请求,并且一个Post请求只能有一个@RequestBody。 @RequestBody的参数可以包括复杂类型。
然后我们讲一下@RequestParam,@RequestParam可以用在Post和Get请求中,但是要注意:@RequestParam 的参数只能是基本类型或者Enum,或者List和Map(List和Map里面也只能是基本类型)。所以@RequestParam可以和@RequestBody一起使用。
如果我们是Get请求,但是又有复合类型怎么办? 比如我们想传递一个User对象。User对象里面只有普通的两个String属性。 这里我们可以使用@SpringQueryMap:
@GetMapping("getUserAge")
public String getUserAge(@RequestParam("userId") String userId, @SpringQueryMap User user);
注意:@SpringQueryMap后面的参数只能是普通的POJO,不能是复合类型,否则解析不了。如果必须使用复合类型,那么使用@RequestBody吧。
FeignClient的日志问题
OpenFeign的Logger.Level有4种级别:
- NONE 没有日志
- BASIC 请求方法,请求URL,返回Code和执行时间
- HEADERS 请求和返回的头部基本信息
- FULL 请求和返回的头部,内容,元数据
要想使用这些级别,必须将OpenFeignClient的logger设置成debug级别:
#日志配置
logging:
level:
com:
flydean: debug
同时我们在代码中配置OpenFeign的日志级别:
@Configuration
public class CustFeignLogConfig {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
这样我们在日志里面就可以看到DEBUG的所有HTTP请求信息。
多个FeignClient使用同一个name的问题
其实这里我们的Server定义了两个Rest服务,User和Order。
上面我们讲到了可以这样定义UserClient:
@FeignClient(value = "openfeign-server")
@RequestMapping(path = "/user")
public interface UserClient {
...
}
如果我们同样的这样定义OrderClient:
@FeignClient(value = "openfeign-server")
@RequestMapping(path = "/order")
public interface OrderClient {
...
}
运行时候就会报错。 原因是两个FeignClient使用了同一个value!
那怎么解决这个问题呢?
/**
* 因为@FeignClient的value不能重复,所以需要在这里以自定义的方式来创建
* @author wayne
* @version FeignClientController, 2019/9/5 7:07 下午
*/
@Data
@Component
@Import(FeignClientsConfiguration.class)
public class FeignClientController {
private OrderClient orderClient;
private UserClient userClient;
public FeignClientController(Decoder decoder, Encoder encoder, Client client, Contract contract) {
this.orderClient = Feign.builder().client(client)
.encoder(encoder)
.decoder(decoder)
.contract(contract)
//默认是Logger.NoOpLogger
.logger(new Slf4jLogger(OrderClient.class))
//默认是Logger.Level.NONE
.logLevel(Logger.Level.FULL)
.target(OrderClient.class, "http://openfeign-server");
this.userClient = Feign.builder().client(client)
.encoder(encoder)
.decoder(decoder)
.contract(contract)
//默认是Logger.NoOpLogger
.logger(new Slf4jLogger(UserClient.class))
//默认是Logger.Level.NONE
.logLevel(Logger.Level.FULL)
.target(UserClient.class, "http://openfeign-server");
}
}
方法就是手动创建FeignClient, 上面的例子中,我们手动创建了OrderClient和UserClient两个FeignClient。
注意下面的代码片段,手动创建的FeignClient默认是没有logger和logLevel的。所以上面我们配置好的log信息对手动创建的FeignClient是无效的。 下面展示了如何手动添加:
//默认是Logger.NoOpLogger
.logger(new Slf4jLogger(OrderClient.class))
//默认是Logger.Level.NONE
.logLevel(Logger.Level.FULL)
如何运行
本项目的模块都是以spring boot构建的,直接在编译器中运行Main方法即可启动。
- 启动openfeign-registry-server
openfeign-registry-server会启动eureka server,供后面的OpenFeignServer和OpenFeignClient注册。
启动openfeign-server
启动openfeign-client
测试openFeignClient
get请求url: http://localhost:8000/getUserName1
查看日志,看看输出吧。
本项目代码地址 :spring-cloud-openfeign-demo
更多教程请参考 flydean的博客
Spring Cloud OpenFeign使用教程的更多相关文章
- Spring Cloud Alibaba基础教程:支持的几种服务消费方式(RestTemplate、WebClient、Feign)
通过<Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现>一文的学习,我们已经学会如何使用Nacos来实现服务的注册与发现,同时也介绍如何通过LoadBal ...
- Spring Cloud Alibaba基础教程-Nacos(三)
在Spring Cloud Alibaba基础教程-Nacos(二)当中学习了,如何使用 nacos图形化界面操作 ,使用Nacos部署集群,下面我们开始Nacos最后一篇的学习 ,如果对你有帮助,记 ...
- Spring Cloud Alibaba基础教程:Nacos的集群部署
继续说说生产环境的Nacos搭建,通过上一篇<Spring Cloud Alibaba基础教程:Nacos的数据持久化>的介绍,我们已经知道Nacos对配置信息的存储原理,在集群搭建的时候 ...
- Spring Cloud Alibaba基础教程:Nacos的数据持久化
前情回顾: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方式> ...
- Spring Cloud Alibaba基础教程:Nacos配置的多文件加载与共享配置
前情回顾: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方式> ...
- Spring Cloud Alibaba基础教程:Nacos配置的多环境管理
前情回顾: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方式> ...
- Spring Cloud Alibaba基础教程:Nacos配置的加载规则详解
前情回顾: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方式(Res ...
- Spring Cloud Alibaba基础教程:使用Nacos作为配置中心
通过本教程的前两篇: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方 ...
- Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现
自Spring Cloud Alibaba发布第一个Release以来,就备受国内开发者的高度关注.虽然Spring Cloud Alibaba还没能纳入Spring Cloud的主版本管理中,但是凭 ...
随机推荐
- 手写一个Promise/A+,完美通过官方872个测试用例
前段时间我用两篇文章深入讲解了异步的概念和Event Loop的底层原理,然后还讲了一种自己实现异步的发布订阅模式: setTimeout和setImmediate到底谁先执行,本文让你彻底理解Eve ...
- linux硬件资源问题排查:cpu负载、内存使用情况、磁盘空间、磁盘IO
在使用过程中之前正常的功能,突然无法使用,性能变慢,通常都是资源消耗问题,资源消耗可以从以下几个方面去排查.对于已经安装硬件资源监控软件(zabbix)的环境,直接使用硬件资源监控软件(zabbix) ...
- springboot 启动时执行方法
Springboot提供了两种“开机启动”某些方法的方式:ApplicationRunner和CommandLineRunner.下面简单介绍下ApplicationRunner 1.创建个Tests ...
- 剑指offer—单链表反转的三种实现方法
单链表的反转可以用递归.非递归和栈的方法实现 链表节点定义: struct ListNode{ int val; Node* next; ListNode(int x):val(x),next(nul ...
- Springboot系列(四)web静态资源配置详解
Springboot系列(四)web静态资源配置 往期精彩 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 SpringBoot系列(三)配 ...
- 构建LNMP
构建LNMP 案例1:部署LNMP环境 案例2:构建L ...
- shell脚本实现自动压缩一天前的日志文件 ,并传到ftp服务器上
shell脚本实现自动压缩一天前的日志文件 ,并传到ftp服务器上 naonao_127关注2人评论19401人阅读2012-06-08 11:26:16 生产环境下脚本自动备份脚本是 ...
- php设计模式总结
#1 使用设计模式(如建造者.外观.原型和模板模式)更快速.更有效地创建对象 #2 使用数据访问对象和代理设计模式分离体系结构 #3 使用委托.工厂和单元素设计模式改善代码流和控制 #4 在不修改对象 ...
- Java第三十天,I/O操作
一.基本概念 输入输出一般是相对与内存.CPU寄存器.当前进程来说的 输入:从硬盘.键盘等外部设备读取数据到内存.当前进程或CPU寄存器中 输出:利用当前进程将数据写入到硬盘.终端显示屏等外部设备中 ...
- Linux bash篇(四 命令)
1.一次执行多个命令 ; eg: ls -al ; touch data.txt 2.根据情况执行命令 && || cmd1 && c ...