json-rpc是基于json的跨语言远程调用协议,比xml-rpc、webservice等基于文本的协议传输数据格小;相对hessian、Java-rpc等二进制协议便于调试、实现、扩展,是非常优秀的一种远程调用协议。目前主流语言都已有json-rpc的实现框架,java语言中较好的json-rpc实现框架有jsonrpc4j、jpoxy、json-rpc。三者之中jsonrpc4j既可独立使用,又可与spring无缝集合,比较适合于基于spring的项目开发。
向服务端传输数据格式如下:
{ "method": "方法名", "params": [“参数数组”], "id": 方法ID}
说明:
第一个参数: 是方法的名值对
第二个参数: 是参数数组
第三个参数: 是方法ID(可以随意填)
举例: { "method": "doSomething", "params": [], "id": 1234}
doSomething 是远程对象的方法, [] 表示参数为空
{
"jsonrpc": "2.0",
"id": "1234",
"result": null
}
下面展示一个demo,这个demo的主要内容,就是创建一个服务端对象,由客户端进行调用
对象关系
对象关系图如下:
1) 创建一个web projcct工程
2) 创建相应的class,拷贝lib中需要的jar包
3)发布,并运行tomcat
发布myeclipse的tomcat环境,最重要的是web.xml文件,下面展现web.xml的内容
注意: 最后的url,在 "主机:端口"后跟的工程名称,然后是url-pattern
以上图为例: http://127.0.0.1:8080/StudyJsonrpc4j/rpc
1) 实体类
HelloWorldService.java
package com.cwqsolo.demo.enitity;
/*
* 定义一个服务的接口
*/
public interface HelloWorldService {
public HelloWorldBean getDemoBean(String code, String msg);
public Integer getInt(Integer code);
public String getString(String msg);
public void doSomething();
}
HelloWorldBean.java
package com.cwqsolo.demo.enitity;
import java.io.Serializable;
public class HelloWorldBean implements Serializable{
private static final long serialVersionUID = -12345L;
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;
}
}
HelloWorldServiceImpl.javapackage com.cwqsolo.demo.enitity;
public class HelloWorldServiceImpl implements HelloWorldService {
int count=0;
public HelloWorldBean getDemoBean(String code, String msg) {
System.out.println("HelloWorldBean get");
HelloWorldBean bean1 = new HelloWorldBean();
bean1.setCode(Integer.parseInt(code));
bean1.setMsg(msg+",javaBean is fine!");
return bean1;
}
//计算服务端count值与客户端传进来的code值的和
public Integer getInt(Integer code) {
return code+count;
}
//返回某种字符串操作的结果
public String getString(String msg) {
return msg+",server is fine!";
}
//服务端接受调用,执行某些业务动作。这里是count进行技术
public void doSomething() {
count++;
System.out.println("do something"+"; count=>"+count);
}
}
2) 服务端代码
JsonRpcService.java
package com.cwqsolo.demo.server;
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.cwqsolo.demo.enitity.HelloWorldService;
import com.cwqsolo.demo.enitity.HelloWorldServiceImpl;
import com.googlecode.jsonrpc4j.JsonRpcServer;
public class JsonRpcService extends HttpServlet {
private static final long serialVersionUID = 1L;
private JsonRpcServer rpcServer = null;
public JsonRpcService() {
super();
//服务端生成HelloWorldServiceImpl对象,并且提供对应的方法
rpcServer = new JsonRpcServer(new HelloWorldServiceImpl(), HelloWorldService.class );
}
@Override
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
System.out.println("JsonRpcService service being call");
rpcServer.handle(request, response);
}
}
package com.cwqsolo.demo.client;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import com.cwqsolo.demo.enitity.HelloWorldBean;
import com.googlecode.jsonrpc4j.JsonRpcHttpClient;
public class JsonRpcClient{
static JsonRpcHttpClient client;
public JsonRpcClient() {
}
public static void main(String[] args) throws Throwable {
// 实例化请求地址,注意服务端web.xml中地址的配置
try {
client = new JsonRpcHttpClient(new URL(
"http://127.0.0.1:8080/StudyJsonrpc4j/rpc"));
// 请求头中添加的信息,这里可以自己定义
Map headers = new HashMap();
headers.put("Name", "Key");
// 添加到请求头中去
client.setHeaders(headers);
//客户端doSomethine方法,通过调用远程对象的dosomething
JsonRpcClient test = new JsonRpcClient();
//客户端getDemo,是获取远程对象的HelloWorldBean
HelloWorldBean demo = test.getDemo(1, "Hello");
//执行远程对象的get方法
System.out.println("++++++ call remote javabean obj function ++++++");
System.out.println(demo.getCode());
System.out.println(demo.getMsg());
//执行远程对象的方法
int code = test.getInt(10);
System.out.println("++++++ call remote function Integer:first ++++++");
System.out.println(code);
//调用服务端doSomething 方法
test.doSomething();
//第二次调用远程对象的getInt方法
code = test.getInt(10);
System.out.println("++++++ call remote function Integer:second ++++++");
System.out.println(code);
String msg = test.getString("hello");
System.out.println("++++++ Call remote function String ++++++");
System.out.println(msg);
System.out.println("++++++ end ++++++");
} catch (Exception e) {
e.printStackTrace();
}
}
/*
*客户端dosomething 方法,调用服务端的dosomething
*/
public void doSomething() throws Throwable {
client.invoke("doSomething", null);
}
/*
*客户端getDemo 方法,调用服务端的getDemo
*/
public HelloWorldBean getDemo(int code, String msg) throws Throwable {
String[] params = new String[] { String.valueOf(code), msg };
HelloWorldBean demo = null;
demo = client.invoke("getDemoBean", params, HelloWorldBean.class);
return demo;
}
/*
* 客户端getInt 是调用服务端getInt方法
*/
public int getInt(int code) throws Throwable {
Integer[] codes = new Integer[] { code };
return client.invoke("getInt", codes, Integer.class);
}
/*
* 客户端getString 是调用服务端getString方法
*/
public String getString(String msg) throws Throwable {
String[] msgs = new String[] { msg };
return client.invoke("getString", msgs, String.class);
}
}
1) 服务端启动:
在myeclipse的环境下,启动server
信息: Starting Servlet Engine: Apache Tomcat/7.0.30
十二月 12, 2016 4:49:56 下午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory E:\cwqwork\MyEclipse_Workspace\.metadata\.me_tcat7\webapps\StudyJsonrpc4j
十二月 12, 2016 4:49:58 下午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["http-bio-8080"]
十二月 12, 2016 4:49:58 下午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["ajp-bio-8009"]
十二月 12, 2016 4:49:58 下午 org.apache.catalina.startup.Catalina start
信息: Server startup in 2340 ms
可以看到打印出来的日志:
信息: Deploying web application directory E:\cwqwork\MyEclipse_Workspace\.metadata\.me_tcat7\webapps\StudyJsonrpc4j ---表示发布在tomcat环境的工程,在tomcat启动后加载
Server startup in 2340 ms ----表示tomcat启动成功
2) 客户端程序调用
直接运行客户端程序进行调用,在客户端代码类,右键运行:
++++++ call remote javabean obj function ++++++
1
Hello,javaBean is fine!
++++++ call remote function Integer:first ++++++
10
++++++ call remote function Integer:second ++++++
11
++++++ Call remote function String ++++++
hello,server is fine!
++++++ end ++++++
可以看到 first,second调用,返回的结果不同,说明服务端的数据在第一次调用后,数据发生了改写
3)直接浏览器中get方式调用,以代码用doSomething 方法为例
http://127.0.0.1:8080/StudyJsonrpc4j/rpc?method=doSomething&id=1234¶ms=JTViJTVk
说明:params=JTViJTVk, 因为params 参数为空,填入的[],需要转换为 url编码,再转为base64编码,这个编码为 JTViJTVk
调用后,客户端会提示下载,下载后用浏览器打开,里面是调用返回的内容
服务端打印
JsonRpcService service being call
do something; count=>3
用get方法:
在第一个红框处输入: http://127.0.0.1:8080/StudyJsonrpc4j/rpc?method=doSomething&id=1234¶ms=JTViJTVk
第二个红框是send 后,返回的内容
用post 方法:
用POST方式,url 为:http://127.0.0.1:8080/StudyJsonrpc4j/rpc, 点击params 按钮后,在body里面,填入json串
{ "method": "doSomething", "params": [], "id": 1234}
点send 按钮后,在返回区可以看到返回内容