前言
Java远程方法调用,即Java RMI(Java Remote Method Invocation),是Java编程语言里一种用于实现远程过程调用的应用程序编程接口,它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程人员能够在网络环境中分布操作。RMI全部的宗旨就是尽可能的简化远程接口对象的使用。
Java RMI极大地依赖于接口。在需要创建一个远程对象时,程序员通过传递一个接口来隐藏底层的实现细节。客户端得到的远程对象句柄正好与本地的根代码连接,由后者负责透过网络通信,这样一来,程序员只需关心如何通过自己的接口句柄发送消息。
RMI使用示例
在Spring中,同样提供了对RMI的支持,使得在Spring下的RMI开发变得更方便,同样,我们还是通过示例来快速体验RMI所提供的功能。
(1)建立RMI对外接口
public interface HelloRMIService { public int getAdd(int a,int b); }
(2)建立接口实现类
public class HelloRMIServiceImpl implements HelloRMIService { @Override public int getAdd(int a, int b) { return a + b; } }
(3)建立服务端配置文件
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 服务端 --> <bean id="helloRMIServiceImpl" class="com.joe.rmi.HelloRMIServiceImpl"> </bean> <!-- 将类作为一个RMI服务 --> <bean id="myRMI" class="org.springframework.remoting.rmi.RmiServiceExporter"> <!-- 服务类 --> <property name="service" ref="helloRMIServiceImpl"/> <!-- 服务名 --> <property name="serviceName" value="helloRMI"/> <!-- 服务接口 --> <property name="serviceInterface" value="com.joe.rmi.HelloRMIService"/> <!-- 服务端口 --> <property name="registryPort" value="9999"/> </bean> </beans>
(4)建立服务端测试
public static void main(String[] args){ new ClassPathXmlApplicationContext("spring-config.xml"); }
到这里,建立RMI服务端的步骤已经结束了,服务端发布了一个两数相加的对外接口供其他服务器调用。启用服务端测试类,其他机器或端口便可以进行RMI来连接到本机了。
(5)服务端启动
1月 22, 2019 8:57:58 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3dd4520b: startup date [Tue Jan 22 20:57:58 CST 2019]; root of context hierarchy 1月 22, 2019 8:57:58 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring-config.xml] 1月 22, 2019 8:57:58 下午 org.springframework.remoting.rmi.RmiServiceExporter getRegistry 信息: Looking for RMI registry at port '9999' 1月 22, 2019 8:57:59 下午 org.springframework.remoting.rmi.RmiServiceExporter getRegistry 信息: Could not detect RMI registry - creating new one 1月 22, 2019 8:57:59 下午 org.springframework.remoting.rmi.RmiServiceExporter prepare 信息: Binding service 'helloRMI' to RMI registry: RegistryImpl[UnicastServerRef [liveRef: [endpoint:[192.168.248.1:9999](local),objID:[0:0:0, 0]]]]
服务端启动后,发现是一直Run的状态的。
(6)完成后,还需要在测试端建立测试环境以及测试代码,首先建立测试端配置文件
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="myClient" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> <property name="serviceUrl" value="rmi://127.0.0.1:9999/helloRMI"/> <property name="serviceInterface" value="com.joe.rmi.HelloRMIService"/> </bean> </beans>
注意:端口号必须一致;端口号后的url必须与服务端的serviceName一致。
(7)编写测试代码
public class Test { public static void main(String[] args){ //创建Spring上下文(加载bean.xml) ApplicationContext acx= new ClassPathXmlApplicationContext("application.xml"); HelloRMIService service = acx.getBean("myClient",HelloRMIService.class); System.out.println(service.getAdd(1,2)); } }
注意:先启动服务端代码,再启动测试端代码。
(8)启动测试端代码
D:Javajdk-10.0.1injava.exe -javaagent:D:ideaIUlibidea_rt.jar=64915:D:ideaIUin -Dfile.encoding=UTF-8 -classpath E:ideaWorkspaceSpringPracticeoutproductionSpringPractice;E:ideaWorkspaceSpringPracticelibspring-instrument-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-instrument-tomcat-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-aspects-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-context-support-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-aop-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-expression-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-messaging-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-beans-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-orm-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-core-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-jms-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-oxm-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-test-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibcommons-logging-1.2.jar;E:ideaWorkspaceSpringPracticelibaopalliance-1.0.jar;E:ideaWorkspaceSpringPracticelibspring-tx-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-jdbc-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibspring-context-4.3.18.RELEASE.jar;E:ideaWorkspaceSpringPracticelibaspectjweaver-1.8.7.jar;E:ideaWorkspaceSpringPracticelibjavassist-3.9.0.GA.jar com.joe.Test 1月 22, 2019 8:59:28 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@23e028a9: startup date [Tue Jan 22 20:59:28 CST 2019]; root of context hierarchy 1月 22, 2019 8:59:28 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [application.xml] 3
如上所示,输出正确代码3。
上述的测试用例是用一台机器不同的端口来模拟不同机器的RMI连接。在企业的应用中一般都是使用不同的机器来进行RMI服务的发布与访问,你需要将接口打包,并放置在服务端的工程中。
参考:《Spring源码深度解析》 郝佳 编著: