文档章节

远程过程调用RPC RMI(Remote Method Invocation)和Web Service

 风过后
发布于 2017/05/11 11:27
字数 1897
阅读 34
收藏 1

一、RPC是什么

    RPC的全称是Remote Procedure call,是进程间通信方式。

    他允许程序调用另一个地址空间的过程或者函数,不用去关注此过程或函数的实现细节。比如两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数或者方法,由于不在一个内存空间,不能直接调用,这时候需要通过就可以应用RPC框架的实现来解决。

二、RPC的实现

    RPC有很多开源的框架实现这里主要介绍java自带的RMI

    1、RMI是什么

        RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网络分布式应用系统的核心解决方案之一。其实它可以被看作是RPC的Java版本。要求客户端和服务端都要用java实现

    2、RMI简单实例

    (1)服务端代码实现:

    IHello类实现:

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface IHello extends Remote{
	/** 
     * 简单的返回“Hello World!"字样 
     * @return 返回“Hello World!"字样 
     * @throws java.rmi.RemoteException 
     */ 
    public String helloWorld() throws RemoteException; 

    /** 
     * 一个简单的业务方法,根据传入的人名返回相应的问候语 
     * @param someBodyName  人名 
     * @return 返回相应的问候语 
     * @throws java.rmi.RemoteException 
     */ 
    public String sayHelloToSomeBody(String someBodyName) throws RemoteException; 
}

    HelloImpl实现IHello实现:

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class HelloImpl extends UnicastRemoteObject implements IHello{

	protected HelloImpl() throws RemoteException {
		super();
	}

	@Override
	public String helloWorld() throws RemoteException {
		return "Hello Word";
	}

	@Override
	public String sayHelloToSomeBody(String someBodyName) throws RemoteException {
		return "你好," + someBodyName + "!";
	}

}

    HelloServer:

import java.net.MalformedURLException;
import java.nio.channels.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

/** 
* Created by IntelliJ IDEA. 
* Date: 2008-8-7 22:03:35 
* 创建RMI注册表,启动RMI服务,并将远程对象注册到RMI注册表中。 
*/ 
public class HelloServer { 
    public static void main(String args[]) throws java.rmi.AlreadyBoundException { 

        try { 
            //创建一个远程对象 
            IHello rhello = new HelloImpl(); 
            //本地主机上的远程对象注册表Registry的实例,并指定端口为8888,这一步必不可少(Java默认端口是1099),必不可缺的一步,缺少注册表创建,则无法绑定对象到远程注册表上 
            LocateRegistry.createRegistry(8888); 

            //把远程对象注册到RMI注册服务器上,并命名为RHello 
            //绑定的URL标准格式为:rmi://host:port/name(其中协议名可以省略,下面两种写法都是正确的) 
            Naming.bind("rmi://localhost:8888/RHello",rhello); 
//            Naming.bind("//localhost:8888/RHello",rhello); 

            System.out.println(">>>>>INFO:远程IHello对象绑定成功!"); 
        } catch (RemoteException e) { 
            System.out.println("创建远程对象发生异常!"); 
            e.printStackTrace(); 
        } catch (AlreadyBoundException e) { 
            System.out.println("发生重复绑定对象异常!"); 
            e.printStackTrace(); 
        } catch (MalformedURLException e) { 
            System.out.println("发生URL畸形异常!"); 
            e.printStackTrace(); 
        } 
    } 
}

   (2)客户端代码实现:

     新建客户端工程GiveMeWords,客户端需要将服务端的IHello接口拷贝过来,并且必须和服务器端包名相同。否则会报如下错误(本人亲测):

        java.lang.ClassNotFoundException: test.rmi.IHello (no security manager: RMI class loader)

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

public class HelloClient {
	  public static void main(String args[]){ 
	        try { 
	            //在RMI服务注册表中查找名称为RHello的对象,并调用其上的方法 
	            IHello rhello =(IHello) Naming.lookup("rmi://localhost:8888/RHello"); 
	            System.out.println(rhello.helloWorld()); 
	            System.out.println(rhello.sayHelloToSomeBody("熔岩")); 
	        } catch (NotBoundException e) { 
	            e.printStackTrace(); 
	        } catch (MalformedURLException e) { 
	            e.printStackTrace(); 
	        } catch (RemoteException e) { 
	            e.printStackTrace();   
	        } 
	    } 
}

服务端工程结构截图 

客户端工程结构截图

先运行服务器端代码,在运行客户端代码。运行结果:

三、Web Service

    1、WebService是一种跨编程语言和跨操作系统平台的远程调用技术。

        XML+XSD,SOAP和WSDL就是构成WebService平台的三大技术。Web Service采用http协议传输,数据格式为特定格式的XML。

        SOAP协议=HTTP协议+XML协议

        WSDL(Web Service Description Language)基于XML语音的,用于描述Web Service及其函数、参数和返回值。它是WebService客户端和服务器端都能理解的标准格式。WSDL文件保存在Web服务器上,通过一个url地址就可以访问到它。客户端要调用一个WebService服务之前,要知道该服务的WSDL文件的地址。WebService服务提供商可以通过两种方式来暴露它的WSDL文件地址:1.注册到UDDI服务器,以便被人查找;2.直接告诉给客户端调用者。也就是说我们要进行Web Service开发,通过服务器端的WSDL文件,我们就可以编写客户端调用代码。

        服务端代码:

import javax.jws.WebService;
import javax.xml.ws.Endpoint;

@WebService
public class Function {
	public String transWords(String words){
		String res = "";
		for(char ch : words.toCharArray()){
			res += "\t" + ch + "\t";
		}
		return res;
	}
	
	public static void main(String[] args){
		Endpoint.publish("http://localhost:9001/Service/Function", new Function());
		System.out.println("publish success");
	}
}

运行成功后访问http://localhost:9001/Service/Function?wsdl。wsdl文件如下:

<!--
 Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.4-b01. 
-->
<!--
 Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.4-b01. 
-->
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://webService.test/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://webService.test/" name="FunctionService">
<types>
<xsd:schema>
<xsd:import namespace="http://webService.test/" schemaLocation="http://localhost:9001/Service/Function?xsd=1"/>
</xsd:schema>
</types>
<message name="transWords">
<part name="parameters" element="tns:transWords"/>
</message>
<message name="transWordsResponse">
<part name="parameters" element="tns:transWordsResponse"/>
</message>
<portType name="Function">
<operation name="transWords">
<input wsam:Action="http://webService.test/Function/transWordsRequest" message="tns:transWords"/>
<output wsam:Action="http://webService.test/Function/transWordsResponse" message="tns:transWordsResponse"/>
</operation>
</portType>
<binding name="FunctionPortBinding" type="tns:Function">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="transWords">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="FunctionService">
<port name="FunctionPort" binding="tns:FunctionPortBinding">
<soap:address location="http://localhost:9001/Service/Function"/>
</port>
</service>
</definitions>

    WSDL 文档在Web服务的定义中使用下列元素:

  • Types - 数据类型定义的容器,它使用某种类型系统(一般地使用XML Schema中的类型系统)。
  • Message - 通信消息的数据结构的抽象类型化定义。使用Types所定义的类型来定义整个消息的数据结构。
  • Operation - 对服务中所支持的操作的抽象描述,一般单个Operation描述了一个访问入口的请求/响应消息对。
  • PortType - 对于某个访问入口点类型所支持的操作的抽象集合,这些操作可以由一个或多个服务访问点来支持。
  • Binding - 特定端口类型的具体协议和数据格式规范的绑定。
  • Port - 定义为协议/数据格式绑定与具体Web访问地址组合的单个服务访问点。
  • Service- 相关服务访问点的集合。

    然后在客户端项目下运行如下命令 wsimport -s Documents/workspace/GiveMeWords/src -p com.shu.service -keep http://localhost:9001/Service/Function?wsdl 即可自动生成客户端代码

    Documents/workspace/GiveMeWords/src代码位置

    com.shu.service包名

    测试代码:


public class Test {
	/**
	 * 测试webservice此作为客户端
	 * test项目中的webService包下面的Function作为服务端
	 *wsimport -s Documents/workspace/GiveMeWords/src -p com.shu.service -keep http://localhost:9001/Service/Function?wsdl
	 * @param args
	 */
	public static void main(String[] args){
			Function fu = new FunctionService().getFunctionPort();
			String str = fu.transWords("get my words");
			System.out.println(str);
	}
}

    运行即可调用服务端的远程方法transWords()方法。但是客户端怎么知道服务端暴露出来的服务就是transWords呢,还有参数返回值这些客户端是怎么知道的?我们回到上面的WSDL文件:

<portType name="Function">
<operation name="transWords">
<input wsam:Action="http://webService.test/Function/transWordsRequest" message="tns:transWords"/>
<output wsam:Action="http://webService.test/Function/transWordsResponse" message="tns:transWordsResponse"/>
</operation>
</portType>

operation表情表明方法暴露服务的方法名是transWords。<input>标签标示输入参数,<output>函数返回值。这样我们就得到了我们想要的接口了。总之通过WSDL文件我们就可以进行编程。

© 著作权归作者所有

粉丝 1
博文 17
码字总数 16917
作品 0
成都
私信 提问
远程通信的几种选择(RPC,Webservice,RMI,JMS的区别)

RPC(Remote Procedure Call Protocol) RPC使用C/S方式,采用http协议,发送请求到服务器,等待服务器返回结果。这个请求包括一个参数集和一个文本集,通常形成“classname.methodname”形式...

edeis2011
2016/03/25
94
0
远程通信的几种选择(RPC,Webservice,RMI,JMS的区别)

RPC(Remote Procedure Call Protocol) RPC使用C/S方式,采用http协议,发送请求到服务器,等待服务器返回结果。这个请求包括一个参数集和一个文本集,通常形成“classname.methodname”形式...

八戒_o
2016/02/16
200
0
Java RMI之HelloWorld篇

Java RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。可以用此方法调用的任何对象必须实现该...

方绍伟
2013/09/18
0
0
Java RMI那点事儿:初识HelloWorld

Java RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个Java 虚拟机中的对象上的方法。可以用此方法调用的任何对象必须实现该...

BazingaYou
2013/11/08
0
0
如何写第一个RMI程序?

RPC和RMI的关系 RMI全称是Remote Method Invocation(远程方法调用),Java RMI威力体现在它强大的开发分布式网络应用的能力上,是纯Java的网络分布式应用系统的核心解决方案之一。其实它可以被...

jiangmitiao
2016/03/14
34
0

没有更多内容

加载失败,请刷新页面

加载更多

axios 使用步骤很简单,首先在前端项目中,引入 axios:

  前端网络访问,主流方案就是 Ajax,Vue 也不例外,在 Vue2.0 之前,网络访问较多的采用 vue-resources,Vue2.0 之后,官方不再建议使用 vue-resources ,这个项目本身也停止维护,目前建...

SEOwhywhy
30分钟前
3
0
c++ 创建对象的三种方法

c++有三种方法创建对象 结合代码来看 1 #include <iostream> 2 using namespace std; 3 class Test { 4 5 private: 6 public: 7 add() 8 { 9 ......

天王盖地虎626
44分钟前
1
0
ant 中的fileset include等拷贝

拷贝一个目录到指定目录下 例:<copy todir="${basedir}/new"> <fileset dir="${basedir}/old"> <include name="appgen" /> <include name="appgen/" /> <include name=appgen/**" /> <incl......

shzwork
50分钟前
2
0
react-jianshu项目的创建

创建项目 1、github上创建仓库react-jianshu 2、将项目克隆到本地git clone git@github.com:startjcu/react-jianshu.git 3、在当前目录(项目目录的上级目录)下执行create-react-app react-...

星闪海洋
59分钟前
2
0
OSChina 周二乱弹 —— 小哥哥,你可以教我写代码吗

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @nnnm: 生活大爆炸,结束了,这部陪伴了漫长时间的情景喜剧,最终是以诺贝尔奖和大团圆收尾的。虽然,不算精彩,但也是温馨。而少年谢尔顿的...

小小编辑
今天
858
13

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部