Spring Boot 实现不同项目之间的远程
Spring Boot 实现不同项目之间的远程调用
在分布式系统中,通常需要多个微服务之间进行通信。在 Spring Boot 中,实现远程调用的方式有很多,常见的方法包括使用 REST API、gRPC、以及 Spring Cloud Feign 等。本篇博客将详细介绍如何在不同的 Spring Boot 项目之间实现远程调用,并通过代码实例演示具体的实现步骤。
目录
- Spring Boot 实现不同项目之间的远程调用
- 1. 远程调用的基本概念
- 常见的远程调用方式:
- 2. 使用 REST API 进行远程调用
- 示例项目结构:
- `service-a` 项目:
- 1. 创建 Spring Boot 项目
- 2. 定义 REST 控制器
- 3. 启动应用
- `service-b` 项目:
- 1. 创建 Spring Boot 项目
- 2. 创建 REST 客户端
- 3. 创建控制器
- 4. 配置 `RestTemplate` Bean
- 5. 启动应用
- 3. 使用 gRPC 进行远程调用
- 示例项目结构:
- `service-a-grpc` 项目:
- 1. 创建 gRPC 服务定义文件(hello.proto)
- 2. 生成代码
- 3. 实现 gRPC 服务
- 4. 启动 gRPC 服务器
- `service-b-grpc` 项目:
- 1. 创建 gRPC 客户端
- 4. 使用 Spring Cloud OpenFeign 进行远程调用
- 示例项目结构:
- `service-a-feign` 项目:
- 1. 创建 Spring Boot 项目
- 2. 定义 REST 控制器
- 3. 启动应用
- `service-b-feign` 项目:
- 1. 创建 Spring Boot 项目
- 2. 定义 Feign 客户端接口
- 3. 创建控制器
- 4. 启动应用
- 5. 常见问题与解决方案
- 网络延迟
- 服务不可用
- 数据格式不匹配
- 6. 总结
1. 远程调用的基本概念
远程调用是指在分布式系统中,一个服务调用另一个服务提供的方法。远程调用的方式多种多样,主要取决于系统的架构和需求。
常见的远程调用方式:
- REST API:基于 HTTP 协议,通过 URL 访问资源,使用广泛且简单易用。
- gRPC:基于 HTTP/2 协议,使用 Protocol Buffers 作为序列化格式,性能高,支持多种语言。
- Spring Cloud OpenFeign:声明式 HTTP 客户端,简化了 REST API 的调用。
2. 使用 REST API 进行远程调用
REST API 是一种基于 HTTP 协议的调用方式,适用于大多数分布式系统。通过定义统一的接口,客户端可以通过 HTTP 请求调用远程服务。
示例项目结构:
service-a
:提供 REST API 的服务service-b
:调用service-a
提供的 REST API 的服务
service-a
项目:
1. 创建 Spring Boot 项目
使用 Spring Initializr 创建一个新的 Spring Boot 项目,添加 Spring Web
依赖。
2. 定义 REST 控制器
package com.example.servicea.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloController {@GetMapping("/hello/{name}")public String sayHello(@PathVariable String name) {return "Hello, " + name + "!";}
}
3. 启动应用
package com.example.servicea;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class ServiceAApplication {public static void main(String[] args) {SpringApplication.run(ServiceAApplication.class, args);}
}
service-b
项目:
1. 创建 Spring Boot 项目
使用 Spring Initializr 创建一个新的 Spring Boot 项目,添加 Spring Web
和 Spring Boot Starter Web
依赖。
2. 创建 REST 客户端
使用 RestTemplate
进行远程调用。
package com.example.serviceb.client;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;@Service
public class HelloClient {@Autowiredprivate RestTemplate restTemplate;public String getHelloMessage(String name) {String url = "http://localhost:8080/hello/" + name;return restTemplate.getForObject(url, String.class);}
}
3. 创建控制器
package com.example.serviceb.controller;import com.example.serviceb.client.HelloClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloController {@Autowiredprivate HelloClient helloClient;@GetMapping("/getHello/{name}")public String getHello(@PathVariable String name) {return helloClient.getHelloMessage(name);}
}
4. 配置 RestTemplate
Bean
package com.example.serviceb.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@Configuration
public class AppConfig {@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}
5. 启动应用
package com.example.serviceb;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class ServiceBApplication {public static void main(String[] args) {SpringApplication.run(ServiceBApplication.class, args);}
}
3. 使用 gRPC 进行远程调用
gRPC 是一个高性能、开源的 RPC 框架,适用于低延迟和高吞吐量的通信场景。
示例项目结构:
service-a-grpc
:提供 gRPC 服务service-b-grpc
:调用service-a-grpc
提供的 gRPC 服务
service-a-grpc
项目:
1. 创建 gRPC 服务定义文件(hello.proto)
syntax = "proto3";option java_package = "com.example.grpc";
option java_outer_classname = "HelloProto";service HelloService {rpc SayHello (HelloRequest) returns (HelloResponse);
}message HelloRequest {string name = 1;
}message HelloResponse {string message = 1;
}
2. 生成代码
使用 protoc
编译 .proto 文件生成 Java 代码。
3. 实现 gRPC 服务
package com.example.grpc.server;import com.example.grpc.HelloRequest;
import com.example.grpc.HelloResponse;
import com.example.grpc.HelloServiceGrpc;
import io.grpc.stub.StreamObserver;public class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {@Overridepublic void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {String greeting = "Hello, " + request.getName() + "!";HelloResponse response = HelloResponse.newBuilder().setMessage(greeting).build();responseObserver.onNext(response);responseObserver.onCompleted();}
}
4. 启动 gRPC 服务器
package com.example.grpc.server;import io.grpc.Server;
import io.grpc.ServerBuilder;public class GrpcServer {public static void main(String[] args) throws Exception {Server server = ServerBuilder.forPort(8081).addService(new HelloServiceImpl()).build().start();System.out.println("gRPC Server started");server.awaitTermination();}
}
service-b-grpc
项目:
1. 创建 gRPC 客户端
package com.example.grpc.client;import com.example.grpc.HelloRequest;
import com.example.grpc.HelloResponse;
import com.example.grpc.HelloServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;public class GrpcClient {public static void main(String[] args) {ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8081).usePlaintext().build();HelloServiceGrpc.HelloServiceBlockingStub stub = HelloServiceGrpc.newBlockingStub(channel);HelloRequest request = HelloRequest.newBuilder().setName("World").build();HelloResponse response = stub.sayHello(request);System.out.println("Response: " + response.getMessage());channel.shutdown();}
}
4. 使用 Spring Cloud OpenFeign 进行远程调用
Spring Cloud OpenFeign 是一个声明式 HTTP 客户端,它可以简化 REST API 的调用。
示例项目结构:
service-a-feign
:提供 REST API 的服务service-b-feign
:调用service-a-feign
提供的 REST API 的服务
service-a-feign
项目:
1. 创建 Spring Boot 项目
使用 Spring Initializr 创建一个新的 Spring Boot 项目,添加 Spring Web
依赖。
2. 定义 REST 控制器
package com.example.serviceafeign.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloController {@GetMapping("/hello/{name}")public String sayHello(@PathVariable String name) {return "Hello, " + name + "!";}
}
3. 启动应用
package com.example.serviceafeign;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class ServiceAFeignApplication {public static void main(String[] args) {SpringApplication.run(ServiceAFeignApplication.class, args);}
}
service-b-feign
项目:
1. 创建 Spring Boot 项目
使用 Spring Initializr 创建一个新的 Spring Boot 项目,添加 Spring Web
和 Spring Cloud OpenFeign
依赖。
2. 定义 Feign 客户端接口
package com.example.servicebfeign.client;import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient(name = "hello-service", url = "http://localhost:8080")
public interface HelloClient {@GetMapping("/hello/{name}")String sayHello(@PathVariable("name") String name);
}
3. 创建控制器
package com.example.servicebfeign.controller;import com.example.servicebfeign.client.HelloClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloController {@Autowiredprivate HelloClient helloClient;@GetMapping("/getHello/{name}")public String getHello(@PathVariable String name) {return helloClient.sayHello(name);}
}
4. 启动应用
package com.example.servicebfeign;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication
@EnableFeignClients
public class ServiceBFeignApplication {public static void main(String[] args) {SpringApplication.run(ServiceBFeignApplication.class, args);}
}
5. 常见问题与解决方案
在进行远程调用时,可能会遇到一些常见问题,如网络延迟、服务不可用、数据格式不匹配等。以下是一些常见问题及其解决方案:
网络延迟
问题:网络延迟可能导致远程调用耗时较长,影响系统性能。
解决方案:
- 使用异步调用或多线程处理。
- 优化网络配置,减少延迟。
- 使用本地缓存减少远程调用次数。
服务不可用
问题:远程服务不可用可能导致调用失败,影响系统稳定性。
解决方案:
- 实现重试机制,自动重试失败的调用。
- 使用熔断器(如 Spring Cloud Hystrix)保护系统。
- 实现服务发现机制,动态选择可用服务。
数据格式不匹配
问题:客户端和服务器端的数据格式不匹配可能导致序列化/反序列化错误。
解决方案:
- 确保客户端和服务器端使用相同的数据格式和协议版本。
- 使用一致的数据序列化库(如 Protocol Buffers 或 Jackson)。
6. 总结
在本篇博客中,我们详细介绍了如何在不同的 Spring Boot 项目之间实现远程调用,包括使用 REST API、gRPC 和 Spring Cloud OpenFeign 的具体实现方法。通过这些示例代码,相信你已经掌握了基本的实现步骤和注意事项。在实际项目中,根据具体需求选择合适的远程调用方式,可以大大提高系统的性能和可靠性。
希望这篇博客对你有所帮助,如果你有任何问题或建议,欢迎在下方留言讨论。
相关文章:
Spring Boot 实现不同项目之间的远程
Spring Boot 实现不同项目之间的远程调用 在分布式系统中,通常需要多个微服务之间进行通信。在 Spring Boot 中,实现远程调用的方式有很多,常见的方法包括使用 REST API、gRPC、以及 Spring Cloud Feign 等。本篇博客将详细介绍如何在不同的…...

【VS2019安装+QT配置】
【VS2019安装QT配置】 1. 前言2. 下载visual studio20193. visual studio2019安装4. 环境配置4.1 系统环境变量配置4.2 qt插件开发 5. Visual Studio导入QT项目6. 总结 1. 前言 前期安装了qt,发现creator编辑器并不好用,一点都不时髦。在李大师的指导下&…...

敏感信息泄露wp
1.右键查看网页源代码 2.前台JS绕过,ctrlU绕过JS查看源码 3.开发者工具,网络,查看协议 4.后台地址在robots,拼接目录/robots.txt 5.用dirsearch扫描,看到index.phps,phps中有源码,拼接目录,下载index.phps …...
首屏性能优化
* 减少HTTP请求 * 合并css 和 JS 文件, * 图片精灵:将多个小图标合并成一张图片,通过CSS定位显示所需部分 * 内联小型资源:对于一些小的CSS和js代码,直接内联到HTML中 * 优化资源加载 * 延迟加载:对非关…...

HVV | .NET 攻防工具库,值得您拥有!
01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失…...

angular入门基础教程(九)依赖注入(DI)
依赖注入 Angular 中的依赖注入(DI)是框架最强大的特性之一。可以将依赖注入视为 Angular 在运行时为你的应用 提供所需资源的能力。依赖项可以是服务或其他资源。 使用服务的一种方式是作为与数据和 API 交互的方式。为了使服务可重用,应该…...

小学生也能听得懂的大模型 - Transformer 1
参考 [小学生也能听得懂的大模型 Transformer 1]...

听说它可以让代码更优雅
一提到静态代码检查工具这个词应该比较好理解,所谓静态代码检查工具就是检查静态代码的工具,完美~ 言归正传,相信很多程序员朋友都听说过静态代码检查工具这个概念,它可能是我们IDE里的某一个插件,可能是计算机中的一…...

自写ApiTools工具,功能参考Postman和ApiPost
近日在使用ApiPost的时候,发现新版本8和7不兼容,也就是说8不支持离线操作,而7可以。 我想说,我就是因为不想登录使用才从Postman换到ApiPost的。 众所周知,postman时国外软件,登录经常性抽风,…...

《深入浅出WPF》学习笔记一.解析WPF程序
《深入浅出WPF》学习笔记一.解析WPF程序 visual studio帮助我们做了那些事情 引用文件 输出文件类型 按照最原始的方式,我们需要手动打开编译器命令行,使用命令引用类库将代码编译成目标文件。 visual studio会根据我们选择的项目模板,自动…...
Scrapy框架中,如何有效地管理和维护爬虫的日志记录?
在Scrapy框架中,日志记录是监控爬虫行为和调试问题的重要手段。合理地管理和维护爬虫的日志记录,可以帮助开发者更好地了解爬虫的运行状态,并及时发现和解决问题。以下是一些有效管理和维护Scrapy爬虫日志记录的技巧: 1. 配置日志…...
Laravel Sanctum:简化无状态API认证的新纪元
Laravel Sanctum:简化无状态API认证的新纪元 在现代Web应用中,API的安全认证是一个核心需求。Laravel Sanctum是一个轻量级的认证解决方案,专为Laravel开发的单页应用(SPA)、移动应用和API而生。它提供了一种简单而灵…...

OCC BRepOffsetAPI_ThruSections使用
目录 一、BRepOffsetAPI_ThruSections简介 二、功能与特点 三、应用场景 四、示例 一、BRepOffsetAPI_ThruSections简介 在Open CASCADE Technology (OCCT) 中,BRepOffsetAPI_ThruSections 类是用来通过放样生成一个实体或者一个面壳(Shell)。当使用这个类时,isSolid 参…...
driver. findElement()vs Selenium中的Webelement. findElement()
Selenium是一个开源工具,可以自动化Web浏览器并帮助测试Web应用程序。它是Web应用程序测试中使用最广泛的工具之一。在Selenium中,两种常用的查找Web元素的方法是driver.findElement和WebElement.findElement。本文将讨论它们之间的差异。 findElement() 方法声明 WebEl…...
jquery图片懒加载
HTML、 <div><img class"lazyload" alt"" width"1000" data-original"/skin/default/images/BB2.jpg" src"默认图片地址"/><img class"lazyload" alt"" width"1000" data-…...
【端口】-
端口总体上分为硬件端口和软件端口 硬件端口:路由器或者交换机上的硬件端口,硬件端口是不同硬件设备进行交互的接口 软件端口:应用层的各种协议进程与运输实体进行层间交互的一种地址...

【研发日记】Matlab/Simulink技能解锁(十一)——Stateflow中的en、du、ex应用对比
文章目录 前言 项目背景 en类型 du类型 ex类型 组合类型 分析和应用 总结 参考资料 前言 见《【研发日记】Matlab/Simulink技能解锁(六)——六种Simulink模型架构》 见《【研发日记】Matlab/Simulink技能解锁(七)——两种复数移相算法》 见《【研发日记】Matlab/Simul…...

《学会 SpringMVC 系列 · 剖析篇(上)》
📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…...

【Vulnhub系列】Vulnhub_SecureCode1靶场渗透(原创)
【Vulnhub系列靶场】Vulnhub_SecureCode1靶场渗透 原文转载已经过授权 原文链接:Lusen的小窝 - 学无止尽,不进则退 (lusensec.github.io) 一、环境配置 1、从百度网盘下载对应靶机的.ova镜像 2、在VM中选择【打开】该.ova 3、选择存储路径࿰…...

【C语言】结构体详解 -《探索C语言的 “小宇宙” 》
目录 C语言结构体(struct)详解结构体概览表1. 结构体的基本概念1.1 结构体定义1.2 结构体变量声明 2. 结构体成员的访问2.1 使用点运算符(.)访问成员输出 2.2 使用箭头运算符(->)访问成员输出 3. 结构体…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
git: early EOF
macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...