Spring Cloud之远程调用OpenFeign最佳实践

Spring Cloud之远程调用OpenFeign最佳实践

目录

OpenFeign最佳实践

问题引入

Feign 继承方式

创建Module

引入依赖

编写接口

打Jar包

服务提供方

服务消费方

启动服务并访问

Feign 抽取方式

创建Module

引入依赖

编写接口

打Jar包

服务消费方

启动服务并访问

服务部署

修改pom.xml文件

观察Nacos控制台

远程访问


OpenFeign最佳实践

问题引入

最佳实践, 其实也就是经过历史的迭代, 在项⽬中的实践过程中, 总结出来的最好的使⽤⽅式.

通过观察, 我们也能看出来, Feign的客户端与服务提供者的controller代码⾮常相似:

Feign客户端

@FeignClient(value = "product-service",path = "/product") public interface ProductApi { @RequestMapping("/{productId}") ProductInfo getProductById(@PathVariable("productId") Integer productId); }

服务提供方Controller

@RequestMapping("/product") @RestController public class ProductController { @Autowired private ProductService productService; @RequestMapping("/{productId}") public ProductInfo getProductById(@PathVariable("productId") Integer productId){ return productService.selectProductById(productId); } }

那么有没有⼀种⽅法可以简化这种写法呢?

Feign 继承方式
Feign ⽀持继承的⽅式, 我们可以把⼀些常⻅的操作封装到接⼝⾥.
我们可以定义好⼀个接⼝, 服务提供⽅实现这个接⼝, 服务消费⽅编写Feign 接⼝的时候, 直接继承这个接口。
创建Module

接⼝可以放在⼀个公共的Jar包⾥, 供服务提供⽅和服务消费⽅使⽤.

引入依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies>
编写接口

把之前ProductApi的内容移动到Module中的ProductInterface接口中:

package api; import model.ProductInfo; import org.springframework.cloud.openfeign.SpringQueryMap; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; public interface ProductInterface { @RequestMapping("/{productId}") ProductInfo getProductById(@PathVariable("productId") Integer productId); @RequestMapping("/p1") String p1(@RequestParam("id") Integer id); @RequestMapping("/p2") String p2(@RequestParam("id") Integer id, @RequestParam("name") String name); @RequestMapping("/p3") String p3(@SpringQueryMap ProductInfo productInfo); @RequestMapping("/p4") String p4(@RequestBody ProductInfo productInfo); }

把之前ProductInfo的内容移动到Module中:

package model; import lombok.Data; import java.util.Date; @Data public class ProductInfo { private Integer id; private String productName; private Integer productPrice; private Integer state; private Date createTime; private Date updateTime; }

目录结构如下:

打Jar包

通过Maven打包

观察Maven本地仓库, Jar包是否打成功:

服务提供方

服务提供⽅实现接口 ProductInterface

package product.controller; import api.ProductInterface; import model.ProductInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import product.service.ProductService; @RequestMapping("/product") @RestController public class ProductController implements ProductInterface { @Autowired private ProductService productService; @RequestMapping("/{productId}") public ProductInfo getProductById(@PathVariable("productId") Integer productId){ return productService.selectProductById(productId); } @RequestMapping("/p1") public String p1(Integer id){ return "product-service 接收到参数, id:"+id; } @RequestMapping("/p2") public String p2(Integer id, String name){ return "product-service 接收到参数, id:"+id+",name:"+name; } @RequestMapping("/p3") public String p3(ProductInfo productInfo){ return "product-service 接收到参数: productInfo"+productInfo.toString(); } @RequestMapping("/p4") public String p4(@RequestBody ProductInfo productInfo){ return "product-service 接收到参数: productInfo"+productInfo.toString(); } }
服务消费方

服务消费⽅继承ProductInterface

package order.api; import api.ProductInterface; import org.springframework.cloud.openfeign.FeignClient; @FeignClient(value = "product-service",path = "/product") public interface ProductApi extends ProductInterface { }
启动服务并访问
Feign 抽取方式

官⽅推荐Feign的使⽤⽅式为继承的⽅式, 但是企业开发中, 更多是把Feign接⼝抽取为⼀个独⽴的模块(做法和继承相似, 但理念不同).

操作⽅法:
将Feign的Client抽取为⼀个独⽴的模块, 并把涉及到的实体类等都放在这个模块中, 打成⼀个Jar. 服务消费⽅只需要依赖该Jar包即可. 这种⽅式在企业中⽐较常⻅, Jar包通常由服务提供⽅来实现. 

创建Module
引入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
编写接口

把之前ProductApi的内容移动到Module中的ProductInterface接口中:

package api; import model.ProductInfo; import org.springframework.cloud.openfeign.SpringQueryMap; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; public interface ProductInterface { @RequestMapping("/{productId}") ProductInfo getProductById(@PathVariable("productId") Integer productId); @RequestMapping("/p1") String p1(@RequestParam("id") Integer id); @RequestMapping("/p2") String p2(@RequestParam("id") Integer id, @RequestParam("name") String name); @RequestMapping("/p3") String p3(@SpringQueryMap ProductInfo productInfo); @RequestMapping("/p4") String p4(@RequestBody ProductInfo productInfo); }

把之前ProductInfo的内容移动到Module中:

package model; import lombok.Data; import java.util.Date; @Data public class ProductInfo { private Integer id; private String productName; private Integer productPrice; private Integer state; private Date createTime; private Date updateTime; }

目录结构如下:

打Jar包

通过Maven打包

观察Maven本地仓库, Jar包是否打成功:

服务消费方

删除ProductInfo和ProductApi

引入依赖

<dependency> <groupId>com.wmh</groupId> <artifactId>product-api</artifactId> <version>1.0-SNAPSHOT</version> <scope>compile</scope> </dependency>

指定扫描类

下面我们使用@EnableFeignClients(clients = {ProductApi.class})来指定扫描类,

当然也可以使用@EnableFeignClients(basePackages = {"api"})指定扫描类。

package order; import api.ProductApi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; @EnableFeignClients(clients = {ProductApi.class}) @SpringBootApplication public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }

如果不指定扫描类的话,运行程序会失败并报错:

原因是因为order-service的启动类OrderServiceApplication只会扫描启动类所在目录,而ProductApi并不在其扫描路径内,因此需要指定扫描类。

启动服务并访问
服务部署

1. 修改数据库, Nacos等相关配置
2. 对两个服务进⾏打包
Maven打包默认是从远程仓库下载的, product-api 这个包在本地, 有以下解决⽅案:

◦ 上传到Maven中央仓库(⽐较⿇烦)[不推荐]
◦ 搭建Maven私服, 上传Jar包到私服[企业推荐]
◦ 从本地读取Jar包[个⼈学习阶段推荐]

前两种⽅法⽐较复杂, 咱们使⽤第三种⽅式。

修改pom.xml文件

如果不配置上图所示的一下内容,项目启动会失败并报错:

<configuration> <includeSystemScope>true</includeSystemScope> </configuration>

3. 上传jar到Linux服务器
4. 启动Nacos
        启动前最好把data数据删除掉.
5. 启动服务

#后台启动order-service, 并设置输出⽇志到logs/order.log
nohup java -jar order-service.jar >logs/order.log &


#后台启动product-service, 并设置输出⽇志到logs/order.log
nohup java -jar product-service.jar >logs/product-9090.log &


#启动实例, 指定端⼝号为9091
nohup java -jar product-service.jar --server.port=9091 >logs/product-9091.log &
观察Nacos控制台
远程访问

Read more

GCC编译(6)静态库工具AR

GCC编译(6)静态库工具AR

GCC编译(6)静态库工具AR Author: Once Day Date: 2026年2月20日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章可参考专栏: 编译构建工具链_Once-Day的博客-ZEEKLOG博客 参考文章:ar(1) - Linux manual page【Linux】ar命令:用于创建、修改和提取静态库(archive)-ZEEKLOG博客Linux命令学习手册-ar - 知乎Linux ar命令介绍 和常用示例 - Link_Z - 博客园 文章目录 * GCC编译(6)静态库工具AR * 1. AR工具概述 * 1.1 背景介绍 * 1.2 基础使用

By Ne0inhk
基于深度学习的无人机航拍小目标检测算法研究

基于深度学习的无人机航拍小目标检测算法研究

本项目针对无人机航拍场景下的小目标检测问题,基于 YOLO11 系列模型,在 VisDrone 2019 数据集上进行训练与优化,并提供了完整的检测系统桌面应用,支持图片、视频、摄像头的实时检测与训练指标可视化。 一、项目概述 无人机航拍图像具有目标尺度小、密集分布、多尺度混合等特点,传统检测算法难以取得理想效果。本项目采用 Ultralytics YOLO11 框架,结合 VisDrone 数据集进行训练,实现了对行人、车辆等 10 类交通相关目标的高效检测,并配套开发了基于 PyQt6 的桌面应用,便于模型验证与日常使用。 二、数据集 2.1 数据集简介 本项目使用 VisDrone 2019-DET 数据集,由天津大学机器学习与数据挖掘实验室 AISKYEYE 团队发布,对应 ICCV 2019 "Vision

By Ne0inhk
OpenClaw 钉钉群聊多机器人配置完全指南

OpenClaw 钉钉群聊多机器人配置完全指南

OpenClaw 钉钉群聊多机器人配置完全指南 在团队协作中,配置多个专用机器人可以显著提升工作效率——不同的机器人可以分别负责写作、编码、数据分析等不同任务。本文将详细介绍如何在使用OpenClaw的钉钉群聊中配置多个任务机器人,并进一步讲解如何为每个机器人赋予独特的性格和工作规范。 一、钉钉端配置 首先,我们需要在钉钉开放平台创建多个任务机器人。 1.1 创建机器人 1. 按照上述步骤,根据实际需求创建多个机器人。 机器人创建完成后,务必记下 Client ID 和 Client Secret,这些信息后续配置会用到。 访问 钉钉开发者平台,点击立即创建按钮创建任务机器人。 二、OpenClaw端配置 完成钉钉端的配置后,接下来我们在OpenClaw中进行相应的设置(默认已装过钉钉插件)。 # 安装钉钉渠道插件 openclaw plugins install @dingtalk-real-ai/dingtalk-connector # 重启 gateway openclaw gateway restart 2.1 添加 Agent

By Ne0inhk
F076 中医中药知识智能问答与图谱构建研究系统 Vue+Flask+Neo4j

F076 中医中药知识智能问答与图谱构建研究系统 Vue+Flask+Neo4j

文章结尾部分有ZEEKLOG官方提供的学长 联系方式名片 关注B站,私信获取! 麦麦大数据 编号: F076 视频 <<待上传>> 1 系统简介 系统简介:本系统是一个基于Vue+Flask+Neo4j+MySQL构建的《中医中药知识智能问答与图谱构建研究系统》。其核心围绕中医证型、中药信息的数字化管理、智能问答及知识图谱的构建与多维度可视化分析能力展开。 本系统主要面向用户提供中医证型查询、中药推荐、病症知识智能问答等功能,同时面向管理员提供数据分析、用户管理、基础数据维护等系统级管理功能。其关键技术栈涵盖前后端分离架构、图数据库Neo4j、传统关系型数据库MySQL,结合多种文本挖掘算法(如TF-IDF、TextRank、YAKE)完成对数据内容的智能分析。 主要功能模块包括:用户登录与注册、中医证型管理、中药信息展示、知识图谱可视化、智能问答、病症知识推荐、用户画像分析、系统数据管理、个人信息设置等。 2 功能设计

By Ne0inhk