基于jsonrpc4j实现JSON-RPC over HTTP(客户端多种调用方式)

1.说明

前文基于jsonrpc4j实现JSON-RPC over HTTP(服务端集成Spring Boot),
介绍了JSON-RPC over HTTP服务端的实现方法,
并且通过Postman工具调用服务端对外提供的方法,
下面介绍两种基于Java代码调用客户端的方法:

  • 非Spring框架的客户端调用方法
  • 基于Spring框架的客户端调用方法

基于之前服务端的代码开发示例,
下面详细介绍这两种方法的实现。

2.非Spring框架的客户端

不依赖Spring框架的客户端,
实现SON-RPC over HTTP的RPC调用,
只需要依赖jsonrpc4j框架即可:

            <dependency><groupId>com.github.briandilley.jsonrpc4j</groupId><artifactId>jsonrpc4j</artifactId><version>1.6</version></dependency>

新建客户端测试类JsonRpcClientTest.java如下:

package com.ai.json.rpc.client;import java.net.URL;import org.junit.jupiter.api.Test;import com.ai.json.rpc.entity.Book;
import com.ai.json.rpc.service.BookRpcService;
import com.googlecode.jsonrpc4j.JsonRpcHttpClient;
import com.googlecode.jsonrpc4j.ProxyUtil;/*** 测试JSON-RPC over HTTP调用,客户端不依赖Spring Boot,服务端依赖Spring Boot**/
public class JsonRpcClientTest {/*** 基于方法名称的客户端调用*/@Testpublic void testClint2Server() throws Throwable {URL url = new URL("http://localhost:9090/rpc/books");JsonRpcHttpClient client = new JsonRpcHttpClient(url);// 调用JSON RPC服务下的findById方法Book book = client.invoke("findById", new Object[] { "1" }, Book.class);System.out.println(book);}/*** 基于API的客户端调用,需要支持JSON-RPC over HTTP*/@Testpublic void testApi2Server() throws Throwable {URL url = new URL("http://localhost:9090/rpc/books");JsonRpcHttpClient client = new JsonRpcHttpClient(url);// 创建客户端的JSON RPC服务的代理类BookRpcService bookRpcService = ProxyUtil.createClientProxy(getClass().getClassLoader(), BookRpcService.class,client);// 基于API调用findById方法Book book = bookRpcService.findById("2");System.out.println(book);}
}

这里通过JsonRpcHttpClient调用JSON-RPC对外提供的方法:
http://localhost:9090/rpc/books
可以直接通过JsonRpcHttpClient的invoke方法调用,
也可以通过ProxyUtil创建代理类,
通过接口API的方式优雅的调用RPC方法。

3.基于Spring框架的客户端

新建子工程JSON-RPC-SB-client,
pom增加依赖管理如下:

    <dependencies><dependency><groupId>edu.yuwen.protocol</groupId><artifactId>JSON-RPC-SB-api</artifactId><version>${project.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies>

新建启动类JsonRpcClientApplication.java:

package com.ai.json.rpc.client;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class JsonRpcClientApplication {public static void main(String[] args) {SpringApplication.run(JsonRpcClientApplication.class, args);}
}

新建配置类RpcConfiguration.java:

package com.ai.json.rpc.client.config;import java.net.URL;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import com.googlecode.jsonrpc4j.spring.AutoJsonRpcClientProxyCreator;@Configuration
public class RpcConfiguration {private static Logger LOG = LoggerFactory.getLogger(RpcConfiguration.class);@Beanpublic AutoJsonRpcClientProxyCreator rpcClientProxyCreator(@Value("${rpc.client.serverUrl}") String url,@Value("${rpc.client.basePackage}") String basePackage) {LOG.info("配置远程服务端的URL={}, 本地扫描包路径basePackage={}", url, basePackage);AutoJsonRpcClientProxyCreator clientProxyCreator = new AutoJsonRpcClientProxyCreator();try {clientProxyCreator.setBaseUrl(new URL(url));clientProxyCreator.setContentType("application/json");} catch (Exception e) {LOG.error("配置AutoJsonRpcClientProxyCreator发生异常=", e);}clientProxyCreator.setScanPackage(basePackage);return clientProxyCreator;}
}

新建配置文件application.yml:

server:port: 9091rpc:client:serverUrl: http://localhost:9090basePackage: com.ai.json.rpc.service

注意这里依赖了JSON-RPC-SB-api模块,
涉及到的关键代码如下:

package com.ai.json.rpc.service;import com.ai.json.rpc.entity.Book;
import com.googlecode.jsonrpc4j.JsonRpcService;@JsonRpcService("rpc/books")
public interface BookRpcService {public Book findById(String id);
}

4.基于Spring框架的客户端测试

新建测试类JsonRpcContainerTest.java:

package com.ai.json.rpc.client;import java.util.concurrent.TimeUnit;import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import com.ai.json.rpc.entity.Book;
import com.ai.json.rpc.service.BookRpcService;/*** 测试JSON-RPC over HTTP调用,客户端和服务端都依赖Spring Boot容器**/
@SpringBootTest
public class JsonRpcContainerTest {private static Logger LOG = LoggerFactory.getLogger(JsonRpcContainerTest.class);/*** Spring容器注入的rpc服务中已经设置好了远端服务URL*/@Autowiredprivate BookRpcService bookRpcService;@Testpublic void queryBooks() {LOG.info("客户端开始自动查询图书");for (int i = 1; i <= 3; i++) {String id = String.valueOf(i);Book book = bookRpcService.findById(id);LOG.info("根据图书Id={}找到图书Book={}", id, book);try {TimeUnit.SECONDS.sleep(10);} catch (InterruptedException e) {LOG.error("自动查询图书发生异常=", e);}}}
}

通过@SpringBootTest注解启动容器,
可以获得代理过后的BookRpcService实例,
直接调用接口的API即可实现RPC调用。

5.基于Spring框架的客户端使用

类似于上面的测试类,
在业务代码中使用JSON-RPC over HTTP 接口时,
直接注入BookRpcService即可使用,
运行JsonRpcClientApplication启动类后,
会自动注入实际的动态代理类。

新建业务类AutoQueryBookService.java:

package com.ai.json.rpc.client.auto;import java.util.concurrent.TimeUnit;import javax.annotation.PostConstruct;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;import com.ai.json.rpc.entity.Book;
import com.ai.json.rpc.service.BookRpcService;@Component
public class AutoQueryBookService {private static Logger LOG = LoggerFactory.getLogger(AutoQueryBookService.class);/*** Spring容器注入的rpc服务中已经设置好了远端服务URL*/@Autowiredprivate BookRpcService bookRpcService;@PostConstructpublic void queryBooks() {LOG.info("客户端开始自动查询图书");for (int i = 1; i <= 3; i++) {String id = String.valueOf(i);Book book = bookRpcService.findById(id);LOG.info("根据图书Id={}找到图书Book={}", id, book);try {TimeUnit.SECONDS.sleep(10);} catch (InterruptedException e) {LOG.error("自动查询图书发生异常=", e);}}}
}

这里通过@PostConstruct注解,
实现了再容器启动后,
在容器注入BookRpcService实例后,
自动开始执行查询图书的操作,
运行日志如下:

.   ____          _            __ _ _/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \\\/  ___)| |_)| | | | | || (_| |  ) ) ) )'  |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot ::        (v2.3.1.RELEASE)2023-12-11 15:58:24.045  INFO 13568 --- [           main] c.a.j.r.client.JsonRpcClientApplication  : Starting JsonRpcClientApplication on yuwen-asiainfo with PID 13568 (D:\Code\Learn\protocol-impl\RPC-impl\JSON-RPC-impl\JSON-RPC-SpringBoot\JSON-RPC-SB-client\target\classes started by yuwen in D:\Code\Learn\protocol-impl\RPC-impl\JSON-RPC-impl\JSON-RPC-SpringBoot\JSON-RPC-SB-client)
2023-12-11 15:58:24.047  INFO 13568 --- [           main] c.a.j.r.client.JsonRpcClientApplication  : No active profile set, falling back to default profiles: default
2023-12-11 15:58:24.546  INFO 13568 --- [           main] o.s.c.a.ConfigurationClassEnhancer       : @Bean method RpcConfiguration.rpcClientProxyCreator is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
2023-12-11 15:58:24.552  INFO 13568 --- [           main] c.a.j.r.client.config.RpcConfiguration   : 配置远程服务端的URL=http://localhost:9090, 本地扫描包路径basePackage=com.ai.json.rpc.service
2023-12-11 15:58:25.062  INFO 13568 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 9091 (http)
2023-12-11 15:58:25.071  INFO 13568 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-12-11 15:58:25.071  INFO 13568 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.36]
2023-12-11 15:58:25.134  INFO 13568 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-12-11 15:58:25.134  INFO 13568 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1054 ms
2023-12-11 15:58:25.170  INFO 13568 --- [           main] c.a.j.r.c.auto.AutoQueryBookService      : 客户端开始自动查询图书
2023-12-11 15:58:25.358  INFO 13568 --- [           main] c.a.j.r.c.auto.AutoQueryBookService      : 根据图书Id=1找到图书Book=Book [id=1, name=Java核心技术, price=199]
2023-12-11 15:58:35.362  INFO 13568 --- [           main] c.a.j.r.c.auto.AutoQueryBookService      : 根据图书Id=2找到图书Book=Book [id=2, name=人月神话, price=58]
2023-12-11 15:58:45.365  INFO 13568 --- [           main] c.a.j.r.c.auto.AutoQueryBookService      : 根据图书Id=3找到图书Book=Book [id=3, name=程序员养生指南, price=996]
2023-12-11 15:58:55.411  INFO 13568 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2023-12-11 15:58:55.518  INFO 13568 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 9091 (http) with context path ''
2023-12-11 15:58:55.524  INFO 13568 --- [           main] c.a.j.r.client.JsonRpcClientApplication  : Started JsonRpcClientApplication in 31.81 seconds (JVM running for 32.165)

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

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

相关文章

什么是https 加密协议?

什么是https 加密协议&#xff1f; 加密通信的作用加密原理数字证书SSL/TLS 协议部署和使用重要性 HTTPS&#xff08;Hyper Text Transfer Protocol Secure&#xff09;是一种网络传输协议&#xff0c;它是基于HTTP协议的扩展&#xff0c;通过加密通信内容来保障数据传输的安全…

SPI 通信-stm32入门

本节我们将继续学习下一个通信协议 SPI&#xff0c;SPI 通信和我们刚学完的 I2C 通信差不多。两个协议的设计目的都一样&#xff0c;都是实现主控芯片和各种外挂芯片之间的数据交流&#xff0c;有了数据交流的能力&#xff0c;我们主控芯片就可以挂载并操纵各式各样的外部芯片&…

gpu版本的GNN的demo

1、当涉及到在GPU上运行图神经网络&#xff08;GNN&#xff09;时&#xff0c;通常使用深度学习框架&#xff0c;如PyTorch或TensorFlow。在这里&#xff0c;我将为您提供一个使用PyTorch Geometric库实现GNN的简单示例。 首先&#xff0c;确保您已经安装了PyTorch和PyTorch G…

第 375 场 LeetCode 周赛题解

A 统计已测试设备 模拟&#xff1a;记录当前已测试设备数量 class Solution { public:int countTestedDevices(vector<int> &batteryPercentages) {int res 0;int s 0;for (auto x: batteryPercentages) {if (x - s > 0) {res;s;}}return res;} };B 双模幂运算 …

【无线网络技术】——无线城域网(学习笔记)

&#x1f4d6; 前言&#xff1a;无线城域网&#xff08;WMAN&#xff09;是指在地域上覆盖城市及其郊区范围的分布节点之间传输信息的本地分配无线网络。能实现语音、数据、图像、多媒体、IP等多业务的接入服务。其覆盖范围的典型值为3~5km&#xff0c;点到点链路的覆盖可以高达…

少儿编程考级:激发孩子逻辑思维能力的关键

在当今信息化时代&#xff0c;少儿编程已经成为孩子们不可或缺的一项技能。而少儿编程考级&#xff0c;则是检验孩子们在这一技能上所取得的成就的重要途径。少儿编程考级不仅能够激发孩子们的逻辑思维能力&#xff0c;还能够提高他们的动手能力和创造力。6547网将详细介绍少儿…

电源模块测试系统测试LED电源项目的优势

LED电源测试是电源在设计、生产过程中的关键环节&#xff0c;也是确保LED照明产品可靠性和稳定性的重要步骤。LED电源测试一般包括电压、电流、效率、稳定性等。电源模块测试系统测试LED电源&#xff0c;实现自动化测试&#xff0c;保证测试结果的可靠性。 LED电源测试项目及方…

实现加盐加密方法以及MappedByteBuffer,RandomAccess

目录 自己实现 Spring Security MappedByteBuffer RandomAccess 加盐加密的实现 自己实现 传统MD5可通过彩虹表暴力破解&#xff0c; 加盐加密算法是一种常用的密码保护方法&#xff0c;它将一个随机字符串&#xff08;盐&#xff09;添加到原始密码中&#xff0c;然后再进…

力扣17. 电话号码的字母组合(java 回溯法)

Problem: 17. 电话号码的字母组合 文章目录 题目描述思路解题方法复杂度Code 题目描述 思路 题目给定一串数字&#xff0c;要求我们找出所有可能的字母组合&#xff0c;即我们可以穷举出所有可能的结果&#xff0c;而涉及到穷举我们自然可以想到利用回溯来解决问题&#xff0c…

xv6 中的一些系统调用(下)

〇、前言 本文将会结合源代码谈论 sleep、wakeup 这两个系统调用。 一、sleep()系统调用 以下是sleep()函数源码&#xff1a; // Atomically release lock and sleep on chan. // Reacquires lock when awakened. void sleep(void *chan, struct spinlock *lk) {struct pro…

无线且列窄图片如何转excel?

写此文原因&#xff1a;图片要转excel&#xff0c;这放以前&#xff0c;是不能实现的功能&#xff0c;但随着人工智能的蓬勃发展&#xff0c;人们已克服了这一难题&#xff0c;但是&#xff0c;我们知道&#xff0c;要将图片识别成excel&#xff0c;识别程序首先要先识别图片中…

如何在小米路由器4A千兆版刷入OpenWRT并通过内网穿透工具实现公网远程访问

文章目录 前言1. 安装Python和需要的库2. 使用 OpenWRTInvasion 破解路由器3. 备份当前分区并刷入新的Breed4. 安装cpolar内网穿透4.1 注册账号4.2 下载cpolar客户端4.3 登录cpolar web ui管理界面4.4 创建公网地址 5. 固定公网地址访问 前言 OpenWRT是一个高度模块化、高度自…

交易历史记录20231206 记录

昨日回顾&#xff1a; select top 10000 * from dbo.CODEINFO A left join dbo.全部&#xff21;股20231206010101 B ON A.CODE B.代码 left join dbo.全部&#xff21;股20231206CONF D on A.CODED.代码left join dbo.全部&#xff21;股20231206 G on A.CODEG.代码 left…

解决前端跨域问题,后端解决方法

Spring CloudVue前后端分离项目报错&#xff1a;Network Error&#xff1b;net::ERR_FAILED&#xff08;请求跨越&#xff09;-CSDN博客记录自用

Kafka-快速实战

Kafka介绍 ChatGPT对于Apache Kafka的介绍&#xff1a; Apache Kafka是一个分布式流处理平台&#xff0c;最初由LinkedIn开发并于2011年开源。它主要用于解决大规模数据的实时流式处理和数据管道问题。 Kafka是一个分布式的发布-订阅消息系统&#xff0c;可以快速地处理高吞吐…

阿里云国际基于CentOS系统镜像快速部署Apache服务

阿里云轻量应用服务器提供了Windows Server系统镜像和主流的Linux系统镜像&#xff0c;您可以通过该类镜像创建纯净、安全、稳定的运行环境。本文以CentOS 7.6系统镜像为例&#xff0c;介绍如何快速配置Apache服务。 背景信息 注意&#xff0c;阿里云国际通过corebyt注册并充…

使用rawpy.imread读取.RAW格式数据和.dng格式数据(附代码)

.dng格式是一个更兼容、更高效的RAW格式。如果需要在不同软件之间交换RAW文件&#xff0c;或者需要在软件中进行大量编辑&#xff0c;那么.dng格式是一个不错的选择。 目录 一、 .dng格式数据和.RAW格式数据二、 .dng格式数据和.RAW格式数据区别三、安装rawpy包四、读取.dng格式…

Flask应用基础入门总结

【1】使用migrate方式进行数据库连接 使用migrate方式进行数据库连接需要在终端分别运行三行代码&#xff1a; #init&#xff08;运行一次即可&#xff09;&#xff08;此db为自己设置的连接数据库的对象,可以修改&#xff09; flask db init #&#xff08;将orm模型生成迁移…

从零开始搭建企业管理系统(四):集成 Knife4j

集成 Knife4j 前言Knife4j是什么集成 Knife4j引入 pom 依赖添加基础配置启动程序测试完善文档信息编写配置类修改 UserController修改 UserEntity修改 BaseEntity 文档效果图swagger 界面knife4j 界面 前言 前面一小节我们使用postman来进行接口的调试&#xff0c;如果接口一多…

游戏王的题解

目录 原题&#xff1a; 时间&#xff1a;1s 空间&#xff1a;256M 题目描述 输入格式 输出格式 样例输入 样例输出 题目大意&#xff1a; 主要思路&#xff1a; dp转移&#xff1a; dp初始化&#xff1a; 代码&#xff1a; 原题&#xff1a; 时间&#xff1a;1s …