RPC实践(二)JsonRPC实践_虎纠卫的博客-程序员信息网_jsonrpc

技术标签: JAVA  RPC  

一、JsonRPC介绍

json-rpc是基于json的跨语言远程调用协议,比xml-rpc、webservice等基于文本的协议传输数据格小;相对hessian、Java-rpc等二进制协议便于调试、实现、扩展,是非常优秀的一种远程调用协议。目前主流语言都已有json-rpc的实现框架,java语言中较好的json-rpc实现框架有jsonrpc4j、jpoxy、json-rpc。三者之中jsonrpc4j既可独立使用,又可与spring无缝集合,比较适合于基于spring的项目开发。


二、JsonRPC简单说明

1、调用的Json格式

     向服务端传输数据格式如下:
   { "method": "方法名", "params": [“参数数组”], "id":  方法ID}

     说明:

    第一个参数: 是方法的名值对

    第二个参数: 是参数数组

    第三个参数: 是方法ID(可以随意填)

   举例:  { "method": "doSomething", "params": [], "id": 1234}

   doSomething 是远程对象的方法, []  表示参数为空

2、输出的Json格式

{
  "jsonrpc": "2.0",
  "id": "1234",
  "result": null
}


三、JsonRPC的demo

下面展示一个demo,这个demo的主要内容,就是创建一个服务端对象,由客户端进行调用

对象关系

对象关系图如下:


3.1工程搭建

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


3.2代码

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.java
package 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);
    }

}



3) 客户端代码

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<String, String> headers = new HashMap<String, String>();
            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);
    }

}

3.3运行和测试:

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&params=JTViJTVk

说明:params=JTViJTVk, 因为params 参数为空,填入的[],需要转换为 url编码,再转为base64编码,这个编码为 JTViJTVk

调用后,客户端会提示下载,下载后用浏览器打开,里面是调用返回的内容


服务端打印

JsonRpcService service being call
do something; count=>3

4) 可以用postman 工具来测试,用get方法,post方法都能成功

用get方法:


在第一个红框处输入: http://127.0.0.1:8080/StudyJsonrpc4j/rpc?method=doSomething&id=1234&params=JTViJTVk

第二个红框是send 后,返回的内容


用post 方法:


用POST方式,url 为:http://127.0.0.1:8080/StudyJsonrpc4j/rpc, 点击params 按钮后,在body里面,填入json串

 { "method": "doSomething", "params": [], "id": 1234}

点send 按钮后,在返回区可以看到返回内容
















版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/csolo/article/details/53583905

智能推荐

服务器主板支持什么cpu,怎么看主板支持什么CPU(主板和cpu兼容搭配知识)_overlogged的博客-程序员信息网

原标题:怎么看主板支持什么CPU(主板和cpu兼容搭配知识)对于DIY装机新手朋友来说,比较需要注意的就是CPU与主板兼容问题了。一些电脑高手或者电脑场卖家是怎么看主板支持什么cpu呢?他们为何通过主板型号型号,就可以知道搭配什么处理器呢? 其实,要看主板支持什么CPU并不难,对于电脑高手或者DIY电脑卖家来说,由于长期接触硬件,对各硬件型号都非常了解,加之主板和CPU搭配也是有规律的,因此只要知...

Python学习练习:批量移动文件_Sahadev_的博客-程序员信息网

今天想往MP3下点音乐,但是满了,想把里面不喜欢的删了,但是音乐都在各个文件夹下,于是,我希望所有的音乐文件可以移动到一个层面,以供我按照音乐专辑的封面来挑选要删哪个,于是就想写个程序来做一下整理,想想用我擅长的Java来写吧,但是没什么意思,想到一直想学Python,何不拿Python练练手呢?于是:安装环境:2.5,3.4,2.7,我有3个版本,在练习的时候发现有些语法问题,我猜可能是版本

论文阅读笔记:Perceptual Losses for Real-Time Style Transfer and Super-Resolution_yqf113的博客-程序员信息网

这篇文章是ECCV2016的一篇文章,主要是提出了一种全新的Loss用于图像风格转换和图像超分辨。整体框架如上图所示,分为两个网络,图像转换网络和损失网络,其中图像转换网络是深度残差网络,将图片转换为^ y = fW (x) 。我们训练图像转换网络来最小化损失网络的输出值加权和。损失网络部分部分是16层的VGG网络,它的特定层拿出来作为损失函数。我们将这个损失函数与这两个函数作对比实验。在图像风格...

计算机组成原理学习笔记第4章 4.5——存储扩展_Code_流苏的博客-程序员信息网

计算机组成原理学习笔记第4章 4.5——存储扩展。

ROS2GO之系统升级篇(Ubuntu 18.04 + ROS 1 Melodic + ROS 2 Bouncy + V-Rep等)_zhangrelay的博客-程序员信息网

本教程风险极大,请不要轻易尝试。当然此篇方法适用于任何想从Ubuntu 16.04升级到18.04(10年超长期支持)的用户。----过程如下::[email protected]:~$ sudo apt [email protected]:~$ sudo apt [email protected]:~$ sudo apt install -...

【知识图谱】Neo4j Cypher查询语言详解_ZSYL的博客-程序员信息网_neo4j查询语句

Cypher 语法学习Cypher介绍启动 Neo4j基本类型数值,布尔,字符串节点和关系列表匹配语句根据标签匹配节点根据标签和属性匹配节点匹配任意关系可选匹配过滤匹配路径长度匹配CREATE 命令创建节点创建关系混合使用MERGE 命令SET 子句SHORTESTPATH 函数DELETE 删除和 REMOVE 删除删除属性删除节点和边清空数据库FOREACH 函数总结Cypher介绍Cypher 是图形数据库 Neo4j 的查询语言,就像 SQL 在关系型数据库中查询一样。Cypher 受到不同方

随便推点

Django(1) - Django介绍及环境搭建_狄鸠的博客-程序员信息网

一,Django:Web应用框架Django是个什么东西?Web应用(程序)框架互联网(电网)----&gt; 传递信息,数据(传电)Web应用分为两类:1,服务器程序(发电厂) 2,应用程序(电器)服务器程序:接收传递数据(使用apache,nginx构建等)WSGI:处理服务器程序和应用程序连接问题应用程序(电器),Web应用框架:工作原理Django:全能型的Web框架Tornado:异步的Web框架二,设计模式mtv-m models模型:负责业务数据对象

[HNOI2002]营业额统计(SplayTree)_focus_best的博客-程序员信息网

[HNOI2002]营业额统计(SplayTree)http://www.lydsy.com/JudgeOnline/problem.php?id=1588题意:给你n个数,要你求出每个数的最小波动值之和.第一个数的波动值就是自己,之后第i个数的最小波动值=|val[i]-x|.其中x是与val[i]之差绝对值最小的之前出现过的数.分析:构建一个SplayTree,支持插入节点,找

IDEA修改文件后颜色没变化_口口不是程序员的博客-程序员信息网_idea修改的代码没有变颜色

DEA修改文件后颜色没变化换了台电脑重新配了各种项目环境,SVN也装了,但是发现代码拉下来在IDEA里配好跑起来后,原本修改了的文件应该会变成蓝色、修改了的代码行左侧栏也有相应的颜色改变(如下图),但是实际上并没有变化。原以为是IDEA的配置有问题,然后在网上找了各种配置方法,有教怎么改其他颜色的,有教版本控制里设置目录和VCS的,还有让代码还原再试的等等等。。。检查后半天也没觉得自己配置有问题,最终找到了一个说是安装SVN一路next没勾选command line client tools这一项,

golang静态代码检查_关于Golang的代码审查和质量评估_weixin_39760857的博客-程序员信息网

代码质量一直是每个研发团队关心的问题,提高代码质量一般会从测试驱动开发(TDD),验收测试驱动开发(ATDD),持续集成(CI),代码审查,静态分析工具,编码标准等多个方面入手,在此我想说说代码审查以及静态分析工具和编码标准。代码审查代码审查(英语:Code review)是指对计算机源代码系统化地审查,常用软件同行评审的方式进行,其目的是在找出及修正在软件开发初期未发现的错误,提升软件质量及开发...

语音识别技术基础理解_编程大乐趣的博客-程序员信息网

语音识别是以语音为研究对象,通过语音信号处理和模式识别让机器自动识别和理解人类口述的语言。语音识别技术就是让机器通过识别和理解过程把语音信号转变为相应的文本或命令的高技术。语音识别是一门涉及面很广的交叉学科,它与声学、语音学、语言学、信息理论、模式识别理论以及神经生物学等学科都有非常密切的关系。语音识别技术正逐步成为计算机信息处理技术中的关键技术,语音技术的应用已经成为一个具有竞争性的新兴高技术产...

Docker_南 城的博客-程序员信息网

Docker概念Docker是一种运行于 Linux 和 Windows 上的软件,用于创建、管理和编排容器。Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。总体来说,Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应

推荐文章

热门文章

相关标签