远程过程调用RPC RMI(Remote Method Invocation)和Web Service
2019独角兽企业重金招聘Python工程师标准>>>
一、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();}@Overridepublic String helloWorld() throws RemoteException {return "Hello Word";}@Overridepublic 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文件我们就可以进行编程。
转载于:https://my.oschina.net/u/579493/blog/897359
总结
以上是生活随笔为你收集整理的远程过程调用RPC RMI(Remote Method Invocation)和Web Service的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 启动流程和系统管理
- 下一篇: 记一次培训机构“面试”过程