SpringBoot里使用RMI进行远程方法调用

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

posted @ 2019-03-31 14:58  夏威夷8080  阅读(5406)  评论(2编辑  收藏  举报