RMI,远程方法调用(Remote Method Invocation)是Enterprise JavaBeans的支柱,是建立分布式Java应用程序的方便途径。RMI是非常容易使用的,但是它非常的强大。
RMI的基础是接口,RMI构架基于一个重要的原理:定义接口和定义接口的具体实现是分开的。下面我们通过具体的例子,建立一个简单的远程计算服务和使用它的客户程序
一个正常工作的RMI系统由下面几个部分组成:
远程服务的接口定义
远程服务接口的具体实现
桩(Stub)和框架(Skeleton)文件
一个运行远程服务的服务器
一个RMI命名服务,它允许客户端去发现这个远程服务
类文件的提供者(一个HTTP或者FTP服务器)
一个需要这个远程服务的客户端程序
下面我们一步一步建立一个简单的RMI系统。首先在你的机器里建立一个新的文件夹,以便放置我们创建的文件,为了简单起见,我们只使用一个文件夹存放客户端和服务端代码,并且在同一个目录下运行服务端和客户端。
如果所有的RMI文件都已经设计好了,那么你需要下面的几个步骤去生成你的系统:
1、 编写并且编译接口的Java代码
2、 编写并且编译接口实现的Java代码
3、 编写spring配置文件
5、 编写RMI的客户端程序
6、 安装并且运行RMI系统
第一步
编写服务端提供远程调用的接口
public interface RmiService {
/**
*
* @return
* @throws RemoteException
*/
public List<PersonEntity> getPersonByCat(Cat cat) throws RemoteException;
}
第二部 为远程接口提供实现
public class RmiServiceImpl implements RmiService{
public static Map<Cat, List<PersonEntity>> mapDb= new ConcurrentHashMap<Cat, List<PersonEntity>>();
static{
List<PersonEntity> list1 = new ArrayList<PersonEntity>();
list1.add(new PersonEntity(1,"sun",31));
list1.add(new PersonEntity(2,"zhu",32));
list1.add(new PersonEntity(3,"sa",13));
mapDb.put(new Cat(1,"熊猫","green"), list1);
List<PersonEntity> list2 = new ArrayList<PersonEntity>();
list2.add(new PersonEntity(3,"sun1",31));
list2.add(new PersonEntity(4,"zhu2",32));
list2.add(new PersonEntity(5,"sa3",13));
mapDb.put(new Cat(1,"白马","block"), list2);
}
@Override
public List<PersonEntity> getPersonByCat(Cat cat) throws RemoteException {
return mapDb.get(cat);
}
}
第三部 spring配置 rmi注册服务工厂
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:framework="http://www.300.cn/schema/annotation"
xsi:schemaLocation=" http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.300.cn/schema/annotation
http://www.300.cn/schema/annotation-driven.xsd">
<task:annotation-driven />
<!--2.IOC部分 -->
<!-- 配置IOC组件扫描范围,支持Annotation -Base@Component@Controller@Service@Repostrory -->
<context:component-scan base-package="cn.ce"
annotation-config="true" />
<!--3.AOP部分 -->
<!-- 配置AOP,支持Annotation-Base@Aspectj,并强制使用CGLIG模式 -->
<aop:aspectj-autoproxy proxy-target-class="true"
expose-proxy="true"></aop:aspectj-autoproxy>
<bean id="rmiService" class="rmi.service.impl.RmiServiceImpl"/>
<bean id="serviceExporter" class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="service" ref="rmiService"/>
<!-- 定义服务名 -->
<property name="serviceName" value="rmiService"/>
<property name="serviceInterface" value="rmi.service.RmiService"/>
<property name="registryPort" value="6600"/>
</bean>
</beans>
第四步 客户端应用的spring配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:framework="http://www.300.cn/schema/annotation"
xsi:schemaLocation=" http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.300.cn/schema/annotation
http://www.300.cn/schema/annotation-driven.xsd">
<task:annotation-driven />
<!--2.IOC部分 -->
<!-- 配置IOC组件扫描范围,支持Annotation -Base@Component@Controller@Service@Repostrory -->
<context:component-scan base-package="cn.ce"
annotation-config="true" />
<!--3.AOP部分 -->
<!-- 配置AOP,支持Annotation-Base@Aspectj,并强制使用CGLIG模式 -->
<aop:aspectj-autoproxy proxy-target-class="true"
expose-proxy="true"></aop:aspectj-autoproxy>
<bean id="service" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://172.23.179.27:6600/rmiService"/>
<property name="serviceInterface" value="rmi.service.RmiService"/>
</bean>
</beans>
第五 客户端调用程序
public static void main(String[] args) throws RemoteException {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
RmiService hs = (RmiService) ctx.getBean("service");
List<PersonEntity> list = hs.getPersonByCat(new Cat(1, "熊猫", "green"));
for (PersonEntity entity : list) {
System.out.println("************** \n id:"+entity.getId()+"\n age:"+entity.getAge() + "\n name:"+entity.getName() +"\n ************** \n ");
}
}
注意
本篇使用的是spring2.5 将rmi服务的注册通过spring配置完成 建议实现调用的通用 以rmi工厂类的子类实现rmi服务端信息的动态注册,实现通用的调用接口