Java远程方法调用,即JavaRMI(JavaRemote Method Invocation),是Java编程语言里一种用于实现远程过程调用的应用程序编程接口。它使客户机上的运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程人员能够在网络环境中分布操作。RMI全部的宗旨就是尽可能地简化远程接口对象的使用。
JAVA RMI极大地依赖于接口。在需要创建一个远程对象时,程序员通过传递一个接口来隐藏底层的实现细节。客户端得到的远程对象句柄正好与本地的根代码链接,由后者负责透过网络通信。这样一来,程序员只需关心如何通过自己的接口句柄发送消息。
RMI (Remote Method Invocation)是从JDK 1.1开始就出现的API功能,它让客户端在使用远端服务所提供的服务时,就如何使用本地服务一样,然而RMI在使用时必须一连串繁复的手续,像是服务介面在定义时必须继承Java.rmi.Remote介面、服务Server在实作时必须继承java.rmi.UnicastRemoteObject类别、必须使用rmic指令产生stub与skeleton等,设定上手续繁杂。
Spring RMI实际上是扩展了下javarmi的实现,可以使用bean的xml配置方式使用rmi。可以在Spring中透过org.springframework.remoting.rmi.RmiServiceExporter来简化使用RMI的手续,来实际看看例子,了解Spring在RMI上的使用与简化。
首先定义一个服务接口
package org.spring; public interface RmiService { public String doWork(); public int add(int a, int b); }
服务接口实现
package org.spring; public class RmiServiceImpl implements RmiService{ @Override public String doWork() { return "this message return from server"; } @Override public int add(int a, int b) { return a+b; } }
在Bean定义档中定义,让Spring管理、生成Bean实例,如此即可注册、启动RMI服务
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd" default-autowire="byName"> <bean id="rmiService" class="org.spring.RmiServiceImpl"/> <bean id="serviceExporter" class="org.springframework.remoting.rmi.RmiServiceExporter"> <property name="service"> <ref bean="rmiService"/> </property> <property name="serviceName"> <value>rmiService</value> </property> <property name="serviceInterface"> <value>org.spring.RmiService</value> </property> </bean> </beans>
启动RMI服务
package org.spring; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import org.springframework.context.support.ClassPathXmlApplicationContext; public class RMIServer { public static void main(String[] args) throws IOException { new ClassPathXmlApplicationContext("config/rmi-server.xml"); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); while (true) { if (reader.readLine().equals("exit")) { System.exit(0); } } } }
在客户端,依赖接口对应的jar包就可以了,然后再spring的配置文件中配置好需要访问的服务的地址和对应的接口名称
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd" default-autowire="byName"> <bean id="rmiServiceProxy" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> <property name="serviceUrl"> <value>rmi://localhost/rmiService</value> </property> <property name="serviceInterface"> <value>org.spring.RmiService</value> </property> </bean> </beans>
注意到"serviceUrl"属性的设定,它是以"rmi://"开头,接着指定服务地址与服务名称,写个简单的客户端程式以使用RMI服务器上的服务
package org.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class RMIClient { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("config/rmi-client.xml"); RmiService service = (RmiService) context.getBean("rmiServiceProxy"); String result1 = service.doWork(); System.out.println(result1); int result2 = service.add(1, 2); System.out.println(result2); } }
执行RMIServer.java类,在spring web应用中只要配置文件加载到spring的加载路径即可应用。然后再执行RMIClient.java类。
这样使用spring就能很方便的简化java 的rmi调用,并且由spring管理,在分布式的应用中就能做到客户端只依赖接口,不依赖实现。