Java 远程调用 RMI 与Spring的整合实例

xiaoxiao2021-02-28  94

Java RMI远程调用需要定义远程接口并继承Remote接口,注册并发布远程服务,步骤比较麻烦。Spring框架目的在与减少开发人员重复编码模版代码,简化步骤,让开发人员用简洁的代码开发出良好的安全性高的代码,因此Spring对Java RMI做了良好的封装,大大简化了Java RMI的开发步骤。 Maven 项目搭建: 项目中用来的依赖包 maven pom.xml

<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.0.5.RELEASE</version> </dependency> </dependencies>

项目中用到的实体类Spitter.java

package com.spittr.entity; import java.io.Serializable; public class Spitter implements Serializable { /** * */ private static final long serialVersionUID = 1563056272025335248L; private Long id; private String username; private String password; private String firstName; private String lastName; private String email; public Spitter() {} public Spitter(String username, String password, String firstName, String lastName, String email) { this(null, username, password, firstName, lastName, email); } public Spitter(Long id, String username, String password, String firstName, String lastName, String email) { this.id = id; this.username = username; this.password = password; this.firstName = firstName; this.lastName = lastName; this.email = email; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }

远程接口SpitterService.java

package com.spittr.remote; import java.util.List; import com.spittr.entity.Spitter; public interface SpitterService { public List<Spitter> getRencentSpitters(int count); public void saveSpitter(Spitter spitter); public Spitter getSpitter(long id); }

接口实现SpitterServiceImp.java

package com.spittr.service; import java.util.List; import org.springframework.stereotype.Service; import com.spittr.entity.Spitter; import com.spittr.remote.SpitterService; @Service public class SpitterServiceImp implements SpitterService { @Override public List<Spitter> getRencentSpitters(int count) { // TODO Auto-generated method stub return null; } @Override public void saveSpitter(Spitter spitter) { System.out.println("save done"); } @Override public Spitter getSpitter(long id) { Spitter spitter = new Spitter(); spitter.setUsername("spitter " +id); spitter.setId(id); System.out.println(spitter.getUsername()); System.out.println(spitter); return spitter; } }

Spring 的配置类MainConfig.java

package com.spittr.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.remoting.rmi.RmiServiceExporter; import com.spittr.remote.SpitterService; @Configuration @ComponentScan(basePackages = { "com.spittr.*" }) public class MainConfig{ @Bean public RmiServiceExporter rmiExporter(SpitterService service){ RmiServiceExporter exporter = new RmiServiceExporter(); exporter.setService(service); //serviceName属性用来在RMI注册表中注册一个服务 exporter.setServiceName("SpitterService"); exporter.setServiceInterface(SpitterService.class); return exporter; } }

RmiServiceExporter 类是spring封装了java rmi 的服务发布类,代码中没有指定发布ip和端口,默认发布在本地,和发布在默认端口1099。setServiceName方法是在RMI注册表中注册一个服务,只需要指定服务接口,即可完成最简单的远程调用服务发布。

在Spring容器中启动并发布服务

package com.spittr.main; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import com.spittr.config.MainConfig; public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); System.out.println("服务发布已发布。"); } }

运行结果 服务发布成功! 接下来是编写客户端 项目结构: 实体类和接口与服务类一致 依赖包 pom.xml

<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> </dependencies>

Spring配置类

package com.spittr.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.remoting.rmi.RmiProxyFactoryBean; import com.spittr.remote.SpitterService; @Configuration @ComponentScan(basePackages={"com.spittr.*"}) public class MainConfig { @Bean(name="spitterService") public RmiProxyFactoryBean spitterService(){ RmiProxyFactoryBean proxyFactoryBean = new RmiProxyFactoryBean(); proxyFactoryBean.setServiceUrl("rmi://localhost/SpitterService"); proxyFactoryBean.setServiceInterface(SpitterService.class); return proxyFactoryBean; } }

这里只需要一个RmiProxyFactoryBean,设置绑定的服务和服务类,既可以获得一个代理类,通过proxyFactoryBean.getObject()获得代理类对象。本机和默认端口可以简单指定服务名称proxyFactoryBean.setServiceUrl(“rmi:/SpitterService”);

SpringController.java

package com.spittr.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.remoting.rmi.RmiProxyFactoryBean; import org.springframework.stereotype.Component; import com.spittr.entity.Spitter; import com.spittr.remote.SpitterService; @Component public class SpitterController { private RmiProxyFactoryBean rmiService; private SpitterService spitterService; @Autowired public SpitterController(RmiProxyFactoryBean rmiService) { this.rmiService=rmiService; } public Spitter getSpitter(long id){ spitterService =(SpitterService) rmiService.getObject(); return spitterService.getSpitter(id); } }

rmiService.getObject()是从代理中获得被代理的一个对象,即服务类的一个实例。 测试代码

package spittr.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.remoting.rmi.RmiProxyFactoryBean; import com.spittr.config.MainConfig; import com.spittr.controller.SpitterController; import com.spittr.entity.Spitter; import com.spittr.remote.SpitterService; public class ClientTest { @Test public void clientTest(){ ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); SpitterService spitterService=(SpitterService) applicationContext.getBean("spitterService"); SpitterController spitterController=(SpitterController) applicationContext.getBean(SpitterController.class); Spitter spitter=spitterController.getSpitter(1); System.out.println(spitter); } }

测试结果 客户端 服务端 测试成功!

总结:本人虽然对远程调用的原理不台清楚,这两天有兴趣玩一玩远程调用,按着网上的一个blog写的一个小demo,这样有助于理解远程调用技术的设计思路。

转载请注明原文地址: https://www.6miu.com/read-59316.html

最新回复(0)