一、Java RMI定义
Java RMI:Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程人员能够在网络环境中分布操作。RMI全部的宗旨就是尽可能简化远程接口对象的使用。
二、Java RMI工作原理
RMI能让一个Java程序去调用网络中另一台计算机的Java对象的方法,那么调用的效果就像是在本机上调用一样。通俗的讲:A机器上面有一个class,通过远程调用,B机器调用这个class 中的方法。
RMI,远程方法调用(Remote Method Invocation)是Enterprise JavaBeans的支柱,是建立分布式Java应用程序的方便途径。RMI是非常容易使用的,但是它非常的强大。
RMI的基础是接口,RMI构架基于一个重要的原理:定义接口和定义接口的具体实现是分开的。
三、Java RMI的局限
RMI目前使用Java远程消息交换协议JRMP(Java Remote Messaging Protocol)进行通信。JRMP是专为Java的远程对象制定的协议,由于JRMP是专为Java对象制定的,因此,RMI对于用非Java语言开发的应用系统的支持不足。不能与用非Java语言书写的对象进行通信(意思是只支持客户端和服务器端都是Java程序的代码的远程调用)。
四、结构图
五、代码示例
1.代码工程图
2.rmi-common
这个工程主要是存放client和server都会用到的公共接口。
public interface IUserService { User getUserByName(String username); }
3.rmi-server
主要提供接口的实现以及rmi的服务配置。
@SpringBootApplication
public class RmiBootServer { @Autowired
private IUserService userService; @Autowired
private IPermissionService permissionService; @Bean
public RmiServiceExporter rmiServiceExporter(){
RmiServiceExporter rmiServiceExporter = new RmiServiceExporter();
rmiServiceExporter.setServiceName("userService");
rmiServiceExporter.setService(userService);
rmiServiceExporter.setServiceInterface(IUserService.class);
rmiServiceExporter.setRegistryPort(2002);// 默认为1099,注意占用问题
try {
rmiServiceExporter.afterPropertiesSet();
} catch (RemoteException e) {
e.printStackTrace();
}
return rmiServiceExporter;
} public static void main(String[] args) {
SpringApplication.run(RmiBootServer.class, args);
}
}
@Service
public class UserServiceImpl implements IUserService { @Override
public User getUserByName(String username) {
User user = null;
if (username != null && !username.equals("")) {
user = new User();
if (username.equals("admin")) {
user.setUsername("admin");
user.setPassword("123456");
}else{
user.setUsername("xxxx");
user.setPassword("111111");
} }
return user;
} }
server:
port: 8002
4.rmi-client
本地client如何实现调用远程的接口实现。
@SpringBootApplication
public class RmiBootClient { @Bean
public RmiProxyFactoryBean rmiProxyFactoryBean(){
RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();
rmiProxyFactoryBean.setServiceUrl("rmi://127.0.0.1:2002/userService");
rmiProxyFactoryBean.setServiceInterface(IUserService.class);
return rmiProxyFactoryBean; } public static void main(String[] args) {
SpringApplication.run(RmiBootClient.class, args);
}
}
server:
port: 8001 logging:
level:
root: info
六、测试
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=RmiBootClient.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Slf4j
public class RmiTest { Gson gson = new Gson(); @Autowired
private IUserService userService; @Test
public void getUser(){
log.info("get user{}",gson.toJson(userService.getUserByName("admin")));
}
}
七、代码地址
https://github.com/shaweiwei/sudu-rmi
八、注意点
需要远程传输的java bean一定要实现Serializable接口,具体为啥看这篇 java序列化反序列化深入探究