1、RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,能够让在某个 Java虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。可以用此方法调用的任何对象必须实现该远程接口。调用这样一个对象时,其参数为 "marshalled" 并将其从本地虚拟机发送到远程虚拟机(该远程虚拟机的参数为 "unmarshalled")上。该方法终止时,将编组来自远程机的结果并将结果发送到调用方的虚拟机。如果方法调用导致抛出异常,则该异常将指示给调用方。
2、从我了解RMI开始,我就觉得他和DUBBO的方式差不多,只是dubbo加入了中间件来做管理。RMI在实用性上面还是很不错的。说白了RMI就是像调用本地方法一样调用远程的方法。
3、这里我写了一个demo,主要是了解RMI的实现过程和配置的方式,spring的xml配置方式可以参考我的这个方式来实现。
4、目录结构,为了方便,我这边采用模块的形式来写入
5、父模块springrmi的pom.xml主要是引入依赖和管理模块,不涉及任何代码
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.pinnet</groupId> <artifactId>springrmi</artifactId> <version>1.0-SNAPSHOT</version> <modules> <module>do-common</module> <module>do-client</module> <module>do-server</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>1.5.9.RELEASE</version> </dependency> </dependencies> </project>
6、公共模块do-common这个主要是提供两方共同调用的接口,不涉及业务实现
package com.pinnet.service; public interface IUserService { public String getUser(String name); }
7、RMIserver,这块主要是提供RMI服务,供远程调用
yml配置主要是改变端口
server:
port: 8002
UserServiceImpl主要是实现接口的功能
package com.pinnet.server; import com.pinnet.service.IUserService; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements IUserService { @Override public String getUser(String name) { return "result:"+name; } }
主要就是相关配置:主要是建立RMI服务。
package com.pinnet.config; import com.pinnet.service.IUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.remoting.rmi.RmiServiceExporter; @Configuration public class RmiServer { @Autowired private IUserService userService; @Bean public RmiServiceExporter getRmiServiceExporter() { RmiServiceExporter rmiServiceExporter = new RmiServiceExporter(); rmiServiceExporter.setServiceName("userService"); rmiServiceExporter.setService(userService); rmiServiceExporter.setServiceInterface(IUserService.class); rmiServiceExporter.setRegistryPort(2002); return rmiServiceExporter; } }
8.RMIclient:客户端主要是调用服务,像调用本地一样
yml:主要是改变端口防止占用
server:
port: 8001
RMIclient:配置
package com.pinnet.config; import com.pinnet.service.IUserService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.remoting.rmi.RmiProxyFactoryBean; @Configuration public class RmiClient { @Bean(name = "userService") public RmiProxyFactoryBean getUserService() { RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean(); rmiProxyFactoryBean.setServiceUrl("rmi://127.0.0.1:2002/userService"); rmiProxyFactoryBean.setServiceInterface(IUserService.class); return rmiProxyFactoryBean; } }
调用:
package com.pinnet.init; import com.pinnet.service.IUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @Component public class UserInit implements CommandLineRunner { @Autowired private IUserService userService; @Override public void run(String... strings) throws Exception { System.out.println(userService.getUser("test")); } }
展示:
9、RMI的远程调用方式,很简单也很使用。这个在DUBBO的暴露接口,服务实现的通过zookeeper来注入的过程原理很像。
所以RMI在使用过程中的实用程度还是很高的。本篇博客仅供参考,如有不对,还请指出。