Spring Cloud OpenFeign Demo

之前项目中需要在Spring Cloud中使用OpenFeign的情况,Spring Cloud的版本是目前最新的Greenwich.SR2版本,对应的Spring boot是2.1.7.RELEASE。

在网上找了很多资料,大多言之不详,并且版本也比较低,不适合我的最新版本Spring Cloud的需求。 所以决定还是自己写个教程。

本教程要解决如下几个问题:

  1. 怎么配置OpenFeignServer
  2. 怎么配置OpenFeignClient
  3. 多个参数传递问题
  4. FeignClient的日志问题
  5. 多个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方法即可启动。

  1. 启动openfeign-registry-server

openfeign-registry-server会启动eureka server,供后面的OpenFeignServer和OpenFeignClient注册。

  1. 启动openfeign-server

  2. 启动openfeign-client

  3. 测试openFeignClient

get请求url: http://localhost:8000/getUserName1

查看日志,看看输出吧。

本项目代码地址 :spring-cloud-openfeign-demo

更多教程请参考 flydean的博客

Spring Cloud OpenFeign使用教程的更多相关文章

  1. Spring Cloud Alibaba基础教程:支持的几种服务消费方式(RestTemplate、WebClient、Feign)

    通过<Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现>一文的学习,我们已经学会如何使用Nacos来实现服务的注册与发现,同时也介绍如何通过LoadBal ...

  2. Spring Cloud Alibaba基础教程-Nacos(三)

    在Spring Cloud Alibaba基础教程-Nacos(二)当中学习了,如何使用 nacos图形化界面操作 ,使用Nacos部署集群,下面我们开始Nacos最后一篇的学习 ,如果对你有帮助,记 ...

  3. Spring Cloud Alibaba基础教程:Nacos的集群部署

    继续说说生产环境的Nacos搭建,通过上一篇<Spring Cloud Alibaba基础教程:Nacos的数据持久化>的介绍,我们已经知道Nacos对配置信息的存储原理,在集群搭建的时候 ...

  4. Spring Cloud Alibaba基础教程:Nacos的数据持久化

    前情回顾: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方式> ...

  5. Spring Cloud Alibaba基础教程:Nacos配置的多文件加载与共享配置

    前情回顾: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方式> ...

  6. Spring Cloud Alibaba基础教程:Nacos配置的多环境管理

    前情回顾: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方式> ...

  7. Spring Cloud Alibaba基础教程:Nacos配置的加载规则详解

    前情回顾: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方式(Res ...

  8. Spring Cloud Alibaba基础教程:使用Nacos作为配置中心

    通过本教程的前两篇: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方 ...

  9. Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现

    自Spring Cloud Alibaba发布第一个Release以来,就备受国内开发者的高度关注.虽然Spring Cloud Alibaba还没能纳入Spring Cloud的主版本管理中,但是凭 ...

随机推荐

  1. C++ STL - queue常见函数使用解析

    C++ STL - queue常见函数使用解析 c++队列模板类的定义在头文件中,queue 模板类需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque ...

  2. 国内 Java 开发者必备的两个装备,你配置上了么?

    虽然目前越来越多的国产优秀技术产品走出了国门,但是对于众领域的开发者来说,依然对于国外的各种基础资源依赖还是非常的强.所以,一些网络基本技能一直都是我们需要掌握的,但是速度与稳定性问题一直也都有困扰着 ...

  3. Unity 游戏框架搭建 2019 (二十六) 第一轮整理完结

    昨天呢我们把第八个示例整理完了.整理之后学习了类的第一作用:方法的集合,还有 Obselete 这个 API.并且在进行整理的时候贯彻了我们新的约定和规则:先确保功能有效,再去做变更和删除. 今天我们 ...

  4. 面试官: 说说你对async的理解

    大家好,我是小雨小雨,致力于分享有趣的.实用的技术文章. 内容分为翻译和原创,如果有问题,欢迎随时评论或私信,希望和大家一起进步. 分享不易,希望能够得到大家的支持和关注. TL;DR async是g ...

  5. Nginx知多少系列之(一)前言

    目录 1.前言 2.安装 3.配置文件详解 4.工作原理 5.Linux下托管.NET Core项目 6.Linux下.NET Core项目负载均衡 7.Linux下.NET Core项目Nginx+ ...

  6. flask-文件上传的使用

    flask-文件上传 在flask中使用request.files.get来获取文件对象 对获取到的文件对象可以使用save(filepath)方法来保存文件 上传的文件在保存前需要对文件名做一个过滤 ...

  7. django类视图的装饰器验证

    django类视图的装饰器验证 django类视图的get和post方法是由View内部调用dispatch方法来分发,最后调用as_view来完成一个视图的流程. 函数视图可以直接使用对应的装饰器 ...

  8. Dos 命令启动网卡

    禁用网卡: netsh interface set interface "本地连接" disabled 启用网卡 : netsh interface set interface & ...

  9. Python Requests-学习笔记(5)-响应状态码

    我们可以检测响应状态码: r = requests.get('http://httpbin.org/get') r.status_code 为方便引用,Requests还附带了一个内置的状态码查询对象 ...

  10. hadoop(四)centos7克隆|静态ip|机器名|映射关系|别名配置(完全分布式准备一)|6

    hadoop完全分布式准备工作 克隆默认基础虚拟机三台102/103/104目标:在win10主机上能连上这三台机器,三台机器之间可以互相ping通,用机器名也可ping通.基础虚拟机:创建了文件op ...