一、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序列化反序列化深入探究