当前位置: 首页 > news >正文

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 WebSpring 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 WebSpring 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 实现不同项目之间的远程调用 在分布式系统中&#xff0c;通常需要多个微服务之间进行通信。在 Spring Boot 中&#xff0c;实现远程调用的方式有很多&#xff0c;常见的方法包括使用 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&#xff0c;发现creator编辑器并不好用&#xff0c;一点都不时髦。在李大师的指导下&…...

敏感信息泄露wp

1.右键查看网页源代码 2.前台JS绕过&#xff0c;ctrlU绕过JS查看源码 3.开发者工具&#xff0c;网络&#xff0c;查看协议 4.后台地址在robots,拼接目录/robots.txt 5.用dirsearch扫描&#xff0c;看到index.phps,phps中有源码&#xff0c;拼接目录&#xff0c;下载index.phps …...

首屏性能优化

* 减少HTTP请求 * 合并css 和 JS 文件&#xff0c; * 图片精灵&#xff1a;将多个小图标合并成一张图片&#xff0c;通过CSS定位显示所需部分 * 内联小型资源&#xff1a;对于一些小的CSS和js代码&#xff0c;直接内联到HTML中 * 优化资源加载 * 延迟加载&#xff1a;对非关…...

HVV | .NET 攻防工具库,值得您拥有!

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…...

angular入门基础教程(九)依赖注入(DI)

依赖注入 Angular 中的依赖注入&#xff08;DI&#xff09;是框架最强大的特性之一。可以将依赖注入视为 Angular 在运行时为你的应用 提供所需资源的能力。依赖项可以是服务或其他资源。 使用服务的一种方式是作为与数据和 API 交互的方式。为了使服务可重用&#xff0c;应该…...

小学生也能听得懂的大模型 - Transformer 1

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

听说它可以让代码更优雅

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

自写ApiTools工具,功能参考Postman和ApiPost

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

《深入浅出WPF》学习笔记一.解析WPF程序

《深入浅出WPF》学习笔记一.解析WPF程序 visual studio帮助我们做了那些事情 引用文件 输出文件类型 按照最原始的方式&#xff0c;我们需要手动打开编译器命令行&#xff0c;使用命令引用类库将代码编译成目标文件。 visual studio会根据我们选择的项目模板&#xff0c;自动…...

Scrapy框架中,如何有效地管理和维护爬虫的日志记录?

在Scrapy框架中&#xff0c;日志记录是监控爬虫行为和调试问题的重要手段。合理地管理和维护爬虫的日志记录&#xff0c;可以帮助开发者更好地了解爬虫的运行状态&#xff0c;并及时发现和解决问题。以下是一些有效管理和维护Scrapy爬虫日志记录的技巧&#xff1a; 1. 配置日志…...

Laravel Sanctum:简化无状态API认证的新纪元

Laravel Sanctum&#xff1a;简化无状态API认证的新纪元 在现代Web应用中&#xff0c;API的安全认证是一个核心需求。Laravel Sanctum是一个轻量级的认证解决方案&#xff0c;专为Laravel开发的单页应用&#xff08;SPA&#xff09;、移动应用和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-…...

【端口】-

端口总体上分为硬件端口和软件端口 硬件端口&#xff1a;路由器或者交换机上的硬件端口&#xff0c;硬件端口是不同硬件设备进行交互的接口 软件端口&#xff1a;应用层的各种协议进程与运输实体进行层间交互的一种地址...

【研发日记】Matlab/Simulink技能解锁(十一)——Stateflow中的en、du、ex应用对比

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

《学会 SpringMVC 系列 · 剖析篇(上)》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…...

【Vulnhub系列】Vulnhub_SecureCode1靶场渗透(原创)

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

【C语言】结构体详解 -《探索C语言的 “小宇宙” 》

目录 C语言结构体&#xff08;struct&#xff09;详解结构体概览表1. 结构体的基本概念1.1 结构体定义1.2 结构体变量声明 2. 结构体成员的访问2.1 使用点运算符&#xff08;.&#xff09;访问成员输出 2.2 使用箭头运算符&#xff08;->&#xff09;访问成员输出 3. 结构体…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...