基于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.pswp.cn/news/213743.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/213743.shtml
英文地址,請注明出處:http://en.pswp.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 …