服务端开发,在很多情况下,需要使用到RPC框架,今天发现一款很轻量的RPC框架——JSON-RPC。json rpc 是一种以json为消息格式的远程调用服务,它是一套允许运行在不同操作系统、不同环境的程序实现基于Internet过程调用的规范和一系列的实现。这种远程过程调用可以使用http作为传输协议,也可以使用其它传输协议,传输的内容是json消息体。
json rpc 和xmlrpc相比具有很多优点。首先xmlrpc是以xml作为消息格式,xml具有体积大,格式复杂,传输占用带宽。程序对xml的解析也比较复杂,并且耗费较多服务器资源。json相比xml体积小巧,并且解析相对容易很多。
json-rpc是一种非常轻量级的跨语言远程调用协议,实现及使用简单。仅需几十行代码,即可实现一个远程调用的客户端,方便语言扩展客户端的实现。服务器端有php、java、python、ruby、.net等语言实现,是非常不错的及轻量级的远程调用协议。
其官网地址是:http://www.jsonrpc.org/
其Wiki地址是:http://json-rpc.org/wiki/implementations
可以看到,JSON-RPC有C,C++,C#,Javascipt,Erlang,Objective-C,Java等多种语言的实现,这里我简单介绍下Java使用JSON-RPC的示例,今天折腾了半天弄得。
首先就是要下载jsonrpc4j的jar包以及其依赖的jar包,这里我直接搭建Maven项目,使用Maven来管理jar包,其pom文件如下:

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.hjc.demo</groupId><artifactId>jsonrpc_server</artifactId><packaging>war</packaging><version>0.0.1-SNAPSHOT</version><name>jsonrpc_server Maven Webapp</name><url>http://maven.apache.org</url><dependencies><!-- jsonrpc4j --><dependency><groupId>com.github.briandilley.jsonrpc4j</groupId><artifactId>jsonrpc4j</artifactId><version>1.0</version></dependency><!-- jsonrpc4j依赖的包 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.10</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.0.2</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.0.2</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.0.2</version></dependency><dependency><groupId>javax.portlet</groupId><artifactId>portlet-api</artifactId><version>2.0</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>3.1.2.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>3.1.2.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>3.1.2.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>3.1.2.RELEASE</version></dependency><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.4</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore-nio</artifactId><version>4.2.1</version></dependency><dependency><groupId>org.jmock</groupId><artifactId>jmock-junit4</artifactId><version>2.5.1</version></dependency><dependency><groupId>org.jmock</groupId><artifactId>jmock</artifactId><version>2.5.1</version></dependency><dependency><groupId>org.eclipse.jetty</groupId><artifactId>jetty-server</artifactId><version>9.0.0.RC0</version></dependency><dependency><groupId>org.eclipse.jetty</groupId><artifactId>jetty-servlet</artifactId><version>9.0.0.RC0</version></dependency><dependency><groupId>org.ow2.chameleon.fuchsia.base.json-rpc</groupId><artifactId>org.ow2.chameleon.fuchsia.base.json-rpc.json-rpc-bundle</artifactId><version>0.0.2</version></dependency></dependencies><build><finalName>jsonrpc_server</finalName></build>
</project>

待以上jar包等环境部署好了之后,就可以进行开发了,我们先要部署一个Servlet,作为RPC调用的接口。(我的环境的Tomcat6,Tomcat7的朋友可以直接使用@WebServlet来部署Servlet,具体代码因环境而异)。

web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name>Archetype Created Web Application</display-name><servlet><servlet-name>RpcServer</servlet-name><display-name>RpcServer</display-name><description></description><servlet-class>com.hjc.demo.RpcServer</servlet-class></servlet><servlet-mapping><servlet-name>RpcServer</servlet-name><url-pattern>/rpc</url-pattern></servlet-mapping>
</web-app>

RpcServer.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.hjc.demo;import java.io.IOException;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import com.googlecode.jsonrpc4j.JsonRpcServer;public class RpcServer extends HttpServlet {private static final long serialVersionUID = 1L;private JsonRpcServer rpcServer = null;public RpcServer() {super();rpcServer = new JsonRpcServer(new DemoServiceImply(), DemoService.class);}@Overrideprotected void service(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {rpcServer.handle(request, response);}}

其中,DemoService是RPC调用的接口,DemoServiceImply是DemoService接口的实现,他们的代码分别如下:

DemoService.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.hjc.demo;public interface DemoService {public DemoBean getDemo(String code, String msg);public Integer getInt(Integer code);public String getString(String msg);public void doSomething();
}

DemoServiceImply.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.hjc.demo;public class DemoServiceImply implements DemoService {public DemoBean getDemo(String code, String msg) {DemoBean bean1 = new DemoBean();bean1.setCode(Integer.parseInt(code));bean1.setMsg(msg);return bean1;}public Integer getInt(Integer code) {return code;}public String getString(String msg) {return msg;}public void doSomething() {System.out.println("do something");}}

DemoBean是一个普通的JavaBean,其代码如下:

DemoBean.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.hjc.demo;import java.io.Serializable;public class DemoBean implements Serializable{private static final long serialVersionUID = -5141784402935371524L;private int code;private String msg;public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}
}

以上代码即完成了服务端的代码,接下来写一个客户端的测试类:

JsonRpcTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package com.hjc.test;import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import com.fasterxml.jackson.databind.node.ObjectNode;
import com.googlecode.jsonrpc4j.JsonRpcHttpClient;
import com.hjc.demo.DemoBean;public class JsonRpcTest {static JsonRpcHttpClient client;public JsonRpcTest() {}public static void main(String[] args) throws Throwable {// 实例化请求地址,注意服务端web.xml中地址的配置try {client = new JsonRpcHttpClient(new URL("http://127.0.0.1:8080/jsonrpc_server/rpc"));// 请求头中添加的信息Map<String, String> headers = new HashMap<String, String>();headers.put("UserKey", "hjckey");// 添加到请求头中去client.setHeaders(headers);JsonRpcTest test = new JsonRpcTest();test.doSomething();DemoBean demo = test.getDemo(1, "哈");int code = test.getInt(2);String msg = test.getString("哈哈哈");// printSystem.out.println("===========================javabean");System.out.println(demo.getCode());System.out.println(demo.getMsg());System.out.println("===========================Integer");System.out.println(code);System.out.println("===========================String");System.out.println(msg);System.out.println("===========================end");} catch (Exception e) {e.printStackTrace();}}public void doSomething() throws Throwable {client.invoke("doSomething", null);}public DemoBean getDemo(int code, String msg) throws Throwable {String[] params = new String[] { String.valueOf(code), msg };DemoBean demo = null;demo = client.invoke("getDemo", params, DemoBean.class);return demo;}public int getInt(int code) throws Throwable {Integer[] codes = new Integer[] { code };return client.invoke("getInt", codes, Integer.class);}public String getString(String msg) throws Throwable {String[] msgs = new String[] { msg };return client.invoke("getString", msgs, String.class);}}

最后的打印结果如下:

服务端:

1
do something

客户端:

1
2
3
4
5
6
7
8
===========================javabean
1
哈
===========================Integer
2
===========================String
哈哈哈
===========================end

以上就完成了JSON-RPC全部的代码,值得说的是,这其中我也爬了很多坑,这里也提一下,JsonRpcHttpClient类的invoke方法,如果你要传递参数,必须是一个数组,这里我传的String[]和Integer[],如果传递了别的类型会发生什么呢?你可以试一下这样调用:

1
client.invoke("getInt", 3, Integer.class);

然后你就会发现服务端报错:

1
2
3
4
5
6
7
8
java.lang.IllegalArgumentException: Unknown params node type: 2at com.googlecode.jsonrpc4j.JsonRpcServer.findBestMethodByParamsNode(JsonRpcServer.java:612)at com.googlecode.jsonrpc4j.JsonRpcServer.handleObject(JsonRpcServer.java:373)at com.googlecode.jsonrpc4j.JsonRpcServer.handleNode(JsonRpcServer.java:293)at com.googlecode.jsonrpc4j.JsonRpcServer.handle(JsonRpcServer.java:230)at com.googlecode.jsonrpc4j.JsonRpcServer.handle(JsonRpcServer.java:207)at com.hjc.demo.RpcServer.service(RpcServer.java:24)...

点进源码,你就全明白了,进入JsonRpcServer类查看findBestMethodByParamsNode方法,其代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*** Finds the {@link Method} from the supplied {@link Set} that* best matches the rest of the arguments supplied and returns* it as a {@link MethodAndArgs} class.** @param methods the {@link Method}s* @param paramsNode the {@link JsonNode} passed as the parameters* @return the {@link MethodAndArgs}*/private MethodAndArgs findBestMethodByParamsNode(Set<Method> methods, JsonNode paramsNode) {// no parametersif (paramsNode==null || paramsNode.isNull()) {return findBestMethodUsingParamIndexes(methods, 0, null);// array parameters} else if (paramsNode.isArray()) {return findBestMethodUsingParamIndexes(methods, paramsNode.size(), ArrayNode.class.cast(paramsNode));// named parameters} else if (paramsNode.isObject()) {Set<String> fieldNames = new HashSet<String>();Iterator<String> itr=paramsNode.fieldNames();while (itr.hasNext()) {fieldNames.add(itr.next());}return findBestMethodUsingParamNames(methods, fieldNames, ObjectNode.class.cast(paramsNode));}// unknown params node typethrow new IllegalArgumentException("Unknown params node type: "+paramsNode.toString());}

所以我就明白了,除了null(不传参数),Array,Object,其他的类都是“Unknown params node type”,当时我也很疑惑,Integer不也是Object嘛,断点一下,原来它认为这是IntNode类,所以不能识别,其他的参数我也试过一些,目前还是数组是最靠谱的,网上资料还比较少,希望有懂得给指点指点。

jsonrpc(jsonrpc4j)demo相关推荐

  1. unity demo免费下载:第三人称镜头移动+瞄准线+发射弧线球打击方块(方块可以识别受击方向)demo

    Unity: 第三人称视野移动+瞄准线+发射弧线球打击方块(方块可以识别受击方向)demo 功能描述: 相机能够根据鼠标滑动而移动(类似第三人称游戏镜头控制) 发射弧线的小球 相机视野有辅助线(瞄准线 ...

  2. uni-app 实现echarts地图(河北省)demo例子

    目录 一.效果图 二.下载地址: 一.效果图 二.下载地址: echarts地图(河北省)demo例子

  3. JFormDesigner教程(02)demo演示 java swing插件

    目录 0 前言 1 demo演示 0 前言 在上一篇博客中,讲了如何下载JFormDesigner: https://gitee.com/YFwinston/java-swing/tree/main ...

  4. 快逸报表部署 (一)-- demo连接mysql数据库

    1. 设计器连接mysql数据库, 创建first.raq报表文件 2. 创建demo.jsp,嵌入报表,jsp顶部加入下面两行 <%@ page contentType="text/ ...

  5. RTB matlab工具箱(1)——demo与常用函数

    1. demo rtbdemo 出现工具箱的demo和简单工具 2. 常用函数 2.1 旋转与旋转矩阵 绕某轴旋转a角度: rotx(a); roty(a); rotz(a); rotx(30)=1. ...

  6. 阿里云短信验证(代码)demo完整教程

    前言: 使用阿里云短信服务的前提你得有阿里云账号(我简直在说废话)没有得话就去注册一个 注册后登陆 教程开始: 阿里云上面有官方得文档以及Demo&SDK,为什么我还要写这篇播客呢,因为上面的 ...

  7. Netty 4.1 Getting Start (翻译) + Demo

    一.先来官方入门页面的翻译(翻译不好请多包涵) 入门 本章以简单的例子来介绍Netty的核心概念,以便让您快速入门.当您阅读完本章之后,您就能立即在Netty的基础上写一个客户端和一个服务器. 如果您 ...

  8. 开发者进阶之路 |UIBPlayer (视频播放)demo分享

    本文出自APICloud官方论坛 UIBPlayer 封装了百度云播放器 SDK.本模块带有UI方案,打开后为一个具有完整功能的播放器界面.百度云播放器突破 Android.iOS 平台对视频格式的限 ...

  9. C#——事件(Event)DEMO[闻鸡起舞]

    问题描述 (1) 创建 C#控制台应用程序. (2) 在程序中新建一个表示太阳的类Sun,在其中定义一个事件OnRise,一个成员方法Rise,并在方法中引发事件.参考源代码如下(太阳只有一个,所以将 ...

  10. gulp实用配置(1)——demo

    在React和Vue推进下,现在很多人都在使用webpack作为自动化构建工具,但其实在很多时候我们并不是一定需要用到它,gulp这样的轻量级构建工具就足够了. 最近一段时间不是太忙,所以就写了三份配 ...

最新文章

  1. c语言怎样定义函数举例,c语言怎样定义函数?
  2. python使用笔记
  3. hdu 6852Path6(最短路+最小割)
  4. 关于HTML使用ComDlg ActiveX 无法弹出相应对话框的问题1
  5. P6154 游走 概率dp
  6. C语言 | 直接插入排序
  7. Linux信号实践(1) --Linux信号编程概述
  8. 使用 IAsyncResult 进行 .NET 异步编程
  9. 无向图中两点之间的距离_九上数学:二次函数图像,一动点到两定点距离和最小...
  10. 新年的第一天学习状态感慨
  11. iphone怎么重启_手机卡死了,又不能拆电池!你会怎么处理?
  12. i3-9100f和i5-9400f 的区别
  13. 阿里互联网一线大厂 Java 岗面试题库(2022 年版)
  14. Excel游戏—制作数字炸弹小游戏
  15. 研究方法、技术路线、实验手段、关键技术区别和联系
  16. numpy.arccos详解
  17. fillpolygon
  18. (42)2021-03-01(物体运动、swiper软件、自执行函数)
  19. QT实现一个图片显示器,有登录界面(附图片,源码可直接使用)
  20. 数据库Date数据与字符串如何转换

热门文章

  1. 网上商城系统源码 B2C电子商务系统源码
  2. 微搭低代码中实现二维码生成
  3. Altium designer学习(二)pcb库不求人——立创商城导出封装库
  4. python竖线_python画横线竖线作为分界线
  5. Tomcat内存大小配置及查看内存情况
  6. EasyExecl导出模板,实现动态下拉列
  7. Win10如何为命令提示符增加输入命令获取管理员权限功能?
  8. 考研数学——求极限方法总结
  9. 考研复习 求解函数极限的方法全总结
  10. 刘铎 计算机学院,离散数学及应用 [刘铎 编著] 2013年版