十、Feign客户端

news2024/11/23 0:44:49

目录

1、在springcloud-order项目中引入Feign客户端的依赖

2、在server-order服务的启动类中添加注解@EnableFeignClients

3、使用@FeignClient注解声明Feign客户端需要调用的远程接口

3.1、server-pay服务提供远程接口Controller

3.2、server-member服务提供远程接口Controller

3.3、创建IPayService接口,映射需要调用的pay服务提供的远程接口

3.4、创建IMemberService接口,映射需要调用的member服务提供的远程接口

3.5、在controller中注入接口bean对象,通过调用方法的形式直接调用服务提供者提供的远程接口,更符合开发习惯

3.6、启动服务server-member、server-pay、server-order及server-eureka注册中心

4、OpenFeign客户端对参数的接收

4.1、使用注解@RequestBody接收对象VO参数,否则接收不到传过来的参数

4.2、使用注解@RequestParam("xxx")接收一个普通参数(String/Integer)

4.2.1、在服务提供方和服务调用方提供同样的注解@RequestParam("xxx")

4.2.2、服务提供方不添加@RequestParam("xxx")注解,服务调用方添加@RequestParam("xxx")注解,但是xxx要与服务提供方的参数一致才能映射

4.3、使用@PathVariable接收RESTFul请求路径上的参数

5、FeignClient优雅的使用方式

5.1、在父目录springcloud下创建聚合项目springcloud-api作为公共模块

5.2、在springcloud-api项目的pom文件中引入依赖

5.3、在springcloud-api项目里添加vo对象类和接口

5.4、Maven install项目到maven本地仓库

5.5、在服务提供方server-member和服务调用方server-order引入公共服务模块

5.6、server-member服务端(服务提供方)定义MemberController2 实现api项目中定义的接口

5.7、server-order客户端(服务调用方)定义接口继承api项目中定义的接口


在项目开发中一般访问远程服务接口时并不使用RestTemplate来做,前面已经演示过了怎么通过RestTemplate来访问远程接口,以及基于eureka注册中心的服务发现机制搭配RestTemplate访问远程接口,而使用Feign客户端来访问远程接口是比较常见的做法,其底层实现原理是RPC远程过程调用,同时feign客户端集成了ribbon

1、在springcloud-order项目中引入Feign客户端的依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
</dependencies>

2、在server-order服务的启动类中添加注解@EnableFeignClients

@EnableFeignClients(basePackages = "course.springcloud")

basePackages需要配置openfeign的包扫描路径,扫描FeignClient注解并初始化,如果FeignClient注解的接口和启动类同一个路径下,则不需要配置

3、使用@FeignClient注解声明Feign客户端需要调用的远程接口

注意:接口方法上的注解要与服务提供者提供的注解一致,即请求方式要一致,此外,路径也要一致,否则将映射不到请求

3.1、server-pay服务提供远程接口Controller

@RestController
@RequestMapping("/")
public class PayController {
    @Value("${server.port}")
    private int port;

    @GetMapping("/payInfo")
    public String getPayInfo() {
        return "当前端口为:" + port + "this is pay Info";
    }
}

3.2、server-member服务提供远程接口Controller

@RestController
@RequestMapping("/member")
public class MemberController {

    @Value("${server.port}")
    private int port;

    @GetMapping("/memberInfo")
    public String memberInfo() {
        return "当前请求端口为:" + port + "   this is Member Info";
    }
}

3.3、创建IPayService接口,映射需要调用的pay服务提供的远程接口

// value 配置服务提供者的应用名称或者service id;
// path配置请求的前缀(即服务提供者类上的RequestMapping注解上的路径),// 如果不加这个path前缀,那么方法上的每个请求路径都要写完整请求的路径
@FeignClient(value = "server-pay", path = "/")
public interface IPayService {
    //该注解要与服务提供者的路径及请求方式保持一致,请求方式是GetMapping、PostMapping还是其他,否则映射不到
    @GetMapping("/payInfo")
    String getPayInfo();
}

3.4、创建IMemberService接口,映射需要调用的member服务提供的远程接口

// value 配置服务提供者的应用名称或者service id;
// path配置请求的前缀(即服务提供者类上的RequestMapping注解上的路径)
// 如果不加这个path前缀,那么方法上的每个请求路径都要写完整请求的路径
// 例如下面例子所示:则方法中的GetMapping要写成@GetMapping("/member/memberInfo"),如果方法比较多的话,这么写就比较麻烦
@FeignClient(value = "server-member", path = "/member")
public interface IMemberService {
    //该注解要与服务提供者的路径及请求方式保持一致,请求方式是GetMapping、PostMapping还是其他,否则映射不到
    @GetMapping("/memberInfo")
    String getMemberInfo();
}

3.5、在controller中注入接口bean对象,通过调用方法的形式直接调用服务提供者提供的远程接口,更符合开发习惯

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private IMemberService iMemberService;

    @Autowired
    private IPayService iPayService;

    //使用OpenFeign访问server-member服务的远程接口 /member/memberInfo
    @GetMapping("/getMember")
    public String getMember() {
        return iMemberService.getMemberInfo();
    }

    //使用OpenFeign访问server-pay服务的远程接口 /payInfo
    @GetMapping("/getPay")
    public String getPay() {
        return iPayService.getPayInfo();
    }
}

3.6、启动服务server-member、server-pay、server-order及server-eureka注册中心

3.7、访问接口localhost:9071/order/getPay

3.8、访问接口 localhost:9071/order/getMember

 

 

4、OpenFeign客户端对参数的接收

4.1、使用注解@RequestBody接收对象VO参数,否则接收不到传过来的参数

在server-order、server-member下新增memberVO.class用来设置和接收参数

如果使用了Lombok插件,可以通过注解@Accessors(chain=true)开启链式编程

设置参数时可以简写为New memberVO().setAge(18).setName("张三")

public class memberVO {
    private Integer age;
    private String name;

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
    return "memberVO{" +
            "age=" + age +
            ", name='" + name + '\'' +
            '}';
   }
}

在server-member下的MemberController.class添加addMember方法用来处理新增请求。

@RestController
@RequestMapping("/member")
public class MemberController {
    @PostMapping("/addMember")
    public String addMember(memberVO memberVO) {
        System.out.println(memberVO.toString());
        return "add member success";
    }
}

在server-order下的IMemberService 接口配置feign客户端请求server-member下的远程接口member/addMember

// value 配置服务提供者的应用名称或者service id;
// path配置请求的前缀(即服务提供者类上的RequestMapping注解上的路径)
@FeignClient(value = "server-member", path = "/member")
public interface IMemberService {
    //该注解要与服务提供者的路径及请求方式保持一致,请求方式是GetMapping、PostMapping还是其他,否则映射不到
    @GetMapping("/memberInfo")
    String getMemberInfo();

    @PostMapping("/addMember")
    String addMember(memberVO member);
}

在server-order下的OrderController新增接口/order/addMemberInfo以

访问server-member下的远程接口member/addMember

@RestController
@RequestMapping("/order")
public class OrderController {
    //使用OpenFeign访问server-member服务的远程接口 /member/addMember
    @GetMapping("/addMemberInfo")
    public String addMember() {
        memberVO memberVO = new memberVO();
        memberVO.setAge(18);
        memberVO.setName("张三");
        return iMemberService.addMember(memberVO);
    }
}

重启server-order、server-member,访问接口localhost:9071/order/addMemberInfo

 

由于member服务下的方法请求参数没有添加注解@RequestBody,所以后台打印出来参数值为null.

加上注解后重启server-member服务后再试一次访问刚刚的接口

 

 可以看到已经接收到了请求传过来的参数了

4.2、使用注解@RequestParam("xxx")接收一个普通参数(String/Integer)

4.2.1、在服务提供方和服务调用方提供同样的注解@RequestParam("xxx")

修改server-member下的MemberController.class添加addMember方法

@PostMapping("/addMember")
public String addMember(@RequestParam("test") Integer suqence,@RequestBody memberVO memberVO) {
    System.out.println(memberVO.toString());
    System.out.println(suqence);
    return "add member success";
}

修改server-order下的IMemberService 接口配置feign客户端请求server-member下的远程接口member/addMember

@PostMapping("/addMember")
String addMember(@RequestParam("test") Integer id, @RequestBody memberVO member);

4.2.2、服务提供方不添加@RequestParam("xxx")注解,服务调用方添加@RequestParam("xxx")注解,但是xxx要与服务提供方的参数一致才能映射

修改server-member下的MemberController.class添加addMember方法

@PostMapping("/addMember")
public String addMember(Integer suqence,@RequestBody memberVO memberVO) {
    System.out.println(memberVO.toString());
    System.out.println(suqence);
    return "add member success";
}

修改server-order下的IMemberService 接口配置feign客户端请求

server-member下的远程接口member/addMember

@PostMapping("/addMember")
String addMember(@RequestParam("suqence") Integer id, @RequestBody memberVO member);

修改OrderControlleraddMember方法测试参数接收

@GetMapping("/addMemberInfo")
public String addMember() {
    memberVO memberVO = new memberVO();
    memberVO.setAge(18);
    memberVO.setName("张三");
    return iMemberService.addMember(12,memberVO);
}

重启server-member、server-order服务,重新访问接口localhost:9071/order/addMemberInfo

 同一个方法中可以有多个@@RequestParam("xxx")注解,但是只能有一个@RequestBody注解。

4.3、使用@PathVariable接收RESTFul请求路径上的参数

例如:请求路径为/addMember/{id}/{name}

那么方法上的参数就可以写成addMemberInfo(@PathVariable("id")Integer id,@PathVariable("name")String name)

5、FeignClient优雅的使用方式

由于开发项目的时候,在服务提供方和服务调用方有很多重复的代码,如上面演示的VO对象,在server-member和server-order服务下都有,这样造成了代码冗余,维护起来比较繁杂,因此我们可以新增一个公共服务项目,专门处理这些冗余的代码,然后由服务端实现接口,客户端继承接口

5.1、在父目录springcloud下创建聚合项目springcloud-api作为公共模块

5.2、在springcloud-api项目的pom文件中引入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <scope>provided</scope>
    </dependency>
</dependencies>

5.3、在springcloud-api项目里添加vo对象类和接口

memberVO.class

public class memberVO {
    private Integer age;
    private String name;

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "memberVO{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

IMemberService.class

public interface IMemberService {

    @GetMapping("/memberInfo")
    String getMemberInfo();

    @PostMapping("/addMember")
    String addMember(@RequestParam("test") Integer id, @RequestBody memberVO member);
}

5.4、Maven install项目到maven本地仓库

 5.5、在服务提供方server-member和服务调用方server-order引入公共服务模块

<dependency>
    <groupId>com.chen</groupId>
    <artifactId>springcloud-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

5.6、server-member服务端(服务提供方)定义MemberController2 实现api项目中定义的接口

@RestController
public class MemberController2 implements IMemberService {

    @Value("${server.port}")
    private int port;

    @Override
    public String getMemberInfo() {
        return "当前请求端口为:" + port + "   this is Member Info";
    }

    @Override
    public String addMember(Integer id, memberVO member) {
        System.out.println(member.toString());
        System.out.println(id);
        return "add member success";
    }
}

5.7、server-order客户端(服务调用方)定义接口继承api项目中定义的接口

目的:为了写@FeignClient注解,并把访问路径补全

@FeignClient(value = "server-member", path = "/member")
public interface IMemberService2 extends IMemberService {

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/519182.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ES基础知识总结含SQL、DSL、GOLANG

一、简介 Elasticsearch是一个基于Lucene的全文搜索和分析引擎&#xff0c;Lucene Core是一个完全用Java编写的高性能、全功能搜索引擎库。 它可以快速地存储、实时搜索和分析大量数据。 它可以扩展到上百台服务器&#xff0c;处理PB级数据。PB 2^50 Byte&#xff0c; 在数…

联通数科面试准备

Spring中Bean的生命周期 Spring Bean的生命周期全过程分为5个阶段&#xff0c;创建前准备阶段、创建实例阶段、依赖注入阶段和容器缓存阶段以及销毁实例阶段。 阶段1&#xff1a;创建前准备阶段这个阶段主要是在开始Bean加载之前&#xff0c;从Spring上下文中去获取相关的配置…

如何使用Alchemy开发NFT智能合约(ERC721)

&#x1f978; 本教程翻译自官网&#xff1a;[https://docs.alchemy.com/docs](https://docs.alchemy.com/docs)。对部分内容进行了修改。教程中所有实例经过本人实践&#xff0c;代码可见&#xff1a;https://github.com/ChuXiaoYi/web3Study 使用Solidity开发智能合约并在区块…

2022 第十三届蓝桥杯大赛软件赛决赛, 国赛,C/C++ 大学B组题解

2022 第十三届蓝桥杯大赛软件赛决赛, 国赛&#xff0c;C/C 大学B组题解 文章目录 第1题 —— 2022 &#xff08;5分&#xff09;第2题 —— 钟表 &#xff08;5分&#xff09;第3题 —— 卡牌 &#xff08;10分&#xff09;第4题 —— 最大数字 &#xff08;10分&#xff09;第…

bbys_tu_2016

1,三连 思路&#xff1a;栈溢出 2&#xff0c;IDA分析 利用函数&#xff1a; 思路:ret2text 偏移&#xff1a;24 3&#xff0c;payload from pwn import * context.log_level"debug"rremote(node4.buuoj.cn,29195)flag 0x804856Dpayload 24 * a p32(flag) r.se…

Unittest单元测试框架之unittest构建测试套件

构建测试套件 在实际项目中&#xff0c;随着项目进度的开展&#xff0c;测试类会越来越多&#xff0c;可是直到现在我 们还只会一个一个的单独运行测试类&#xff0c;这在实际项目实践中肯定是不可行的&#xff0c;在 unittest中可以通过测试套件来解决该问题。 测试套件&…

七、Zookeeper注册中心

目录 1、下载Zookeeper的服务jar包 2、下载好jar包后解压放到合适的目录&#xff08;目录最好不要有中文及空格&#xff09; 3、进入解压后的conf目录&#xff0c;复制zoo_sample.cfg文件并重命名为zoo.cfg&#xff0c;修改zoo.cfg文件内容如下 4、运行bin目录下的zkServer…

split,paste,eval命令及正则表达式

一、split命令 将 linux 下的一个大文件拆分成若干小文件 1.语法格式 格式&#xff1a;split 选项 参数 原始文件 拆分后文件名前缀 常用选项: -l&#xff1a;以行数拆分 -b&#xff1a;以大小拆分 2.命令演示 2.1选项 -l &#xff1a;以行数分隔 cat -n anaconda-ks.cfg…

Windows系统安装好MongoDB后运行方法

文章目录 1、先找到安装MongoDB的文件位置的bin文件夹&#xff1a;2、找到data/db文件夹位置&#xff08;如果data文件夹中没有db文件夹需要创建一个&#xff09;&#xff1a;3、在刚刚打开的cmd窗口中运行以下命令&#xff1a;4、再另外从bin文件夹位置开一个cmd窗口&#xff…

图书管理系统(Java简单版)(完整代码+详解)

目录 详解&#xff1a; BookList类&#xff1a; InOperation接口 User类&#xff08;父类&#xff09; 和 Main类&#xff08;这俩要一起看&#xff09; 完整代码 book包 Book类 BookList类 operation包 AddBook类 BorrowBook类 DeleteBook类 FindBook类 Pr…

ESP32 FreeRTOS学习总结

2023.5.11 1.Task 创建任务常用API&#xff1a; 任务函数描述xTaskCreate()使用动态的方法创建一个任务xTaskCreatePinnedToCore指定任务的运行核心(最后一个参数)vTaskDelete(NULL)删除当前任务 BaseType_t xTaskCreate(TaskFunction_t pxTaskCode, // 任…

【HBase】架构

文章目录 整体架构Master负载均衡器元数据管理器预写日志处理器 Region ServerZookeeperHDFS Master架构Meta 表格 RegionServer 架构MemStoreWALBlockCache 读写流程HFile结构写流程读操作 整体架构 Master 实现类为 HMaster。 负责监控集群中所有的 RegionServer 实例。 &…

在Fedora-Workstation-Live-x86_64-36-1.5中使用佳能喷墨打印机ip2780

在Fedora-Workstation-Live-x86_64-36-1.5中使用佳能喷墨打印机ip2780 操作系统是64位的Fedora-Workstation-Live-x86_64-36-1.5.iso&#xff0c;实物打印机是佳能ip2780&#xff0c;USB接口 应用程序——其它——设置——打印机——解锁——输入root密码——将打印机USB插入电…

Redis数据结构——动态字符串、Dict、ZipList

一、Redis数据结构-动态字符串 我们都知道Redis中保存的Key是字符串&#xff0c;value往往是字符串或者字符串的集合。可见字符串是Redis中最常用的一种数据结构。 不过Redis没有直接使用C语言中的字符串&#xff0c;因为C语言字符串存在很多问题&#xff1a; 获取字符串长度…

智慧产业城彰显中国智造魅力,中联重科踏出“走上去”的关键一步

5月11日至14日&#xff0c;中联重科在长沙举行了“科技献礼新时代”系列活动。 借着活动&#xff0c;松果财经实地探访了全球规模最大、品种最全的工程机械产业基地&#xff0c;领略了前沿技术赋能先进制造的魅力。 作为湖南省“一号工程”和“十大重点项目之首”&#xff0c…

好家伙,又一份牛逼笔记面世了...

最近网传的一些裁员的消息&#xff0c;搞的人心惶惶。已经拿到大厂offer的码友来问我&#xff1a;大厂还能去&#xff0c;去了会不会被裁。 还在学习的网友来问我&#xff1a;现在还要冲互联网么&#xff1f; 我是认为大家不用恐慌吧&#xff0c;该看啥看啥&#xff0c;该学啥…

你一定要知道的unittest自动化测试框架详解

目录 框架的概念 Unittest单元测试框架 常用的assert语句 unittest创建测试代码的方式&#xff1a; unittest构建测试套件&#xff08;测试用例集合&#xff09;&#xff1a; unittest忽略测试用例&#xff1a; 运行测试集 批量执行测试用例 生成HTMLTestRunner测试报告…

【运维知识进阶篇】集群架构-Nginx基础(安装+启动+配置+多业务实现+日志管理)

本篇文章介绍下Nginx有关内容&#xff0c;Nginx是一个开源且高性能、可靠的Http Web服务、代理服务。 开源&#xff1a;直接获取源代码&#xff0c;高性能&#xff1a;支持海量并发&#xff0c;可靠&#xff1a;服务稳定 Web服务有很多&#xff0c;选择Nginx是因为他的轻量化…

【软件测试】测试开发的一生之敌-BUG

文章目录 1.前言2.如何描述/创建一个BUG3.BUG的级别4.BUG的生命周期5.跟开发产生争执怎么办 1.前言 BUG相比大家都知道,程序运行出错或者与预期不符就是BUG.现在我们来用测试人员的角度来看待BUG. 2.如何描述/创建一个BUG 测试人员要测试开发人员的代码,找出开发人员可能忽略…