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在使用過程中的實用程度還是很高的。本篇博客僅供參考,如有不對,還請指出。