首页 > 技术文章 > 远程服务(RMI)使用示例

Joe-Go 2019-01-22 21:23 原文

前言

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:\Java\jdk-10.0.1\bin\java.exe -javaagent:D:\ideaIU\lib\idea_rt.jar=64915:D:\ideaIU\bin -Dfile.encoding=UTF-8 -classpath E:\ideaWorkspace\SpringPractice\out\production\SpringPractice;E:\ideaWorkspace\SpringPractice\lib\spring-instrument-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-instrument-tomcat-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-aspects-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-context-support-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-aop-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-expression-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-messaging-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-beans-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-orm-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-core-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-jms-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-oxm-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-test-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\commons-logging-1.2.jar;E:\ideaWorkspace\SpringPractice\lib\aopalliance-1.0.jar;E:\ideaWorkspace\SpringPractice\lib\spring-tx-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-jdbc-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\spring-context-4.3.18.RELEASE.jar;E:\ideaWorkspace\SpringPractice\lib\aspectjweaver-1.8.7.jar;E:\ideaWorkspace\SpringPractice\lib\javassist-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源码深度解析》 郝佳 编著:

推荐阅读