spring rmi的记录,转载的,吃完饭等下自己要用
http://blog.csdn.net/j2ee_dev/article/details/4800693
?
1 RMI的概念
Java Remote Method Invocation (RMI) is Java's remote procedure call (RPC) mechanism. RMI allows you to write distributed objects using Java.
RMI调用的过程,我的理解大致如下:
客户端和服务器端约定好要用于远程调用的方法的接口(包括方法名和输入输出参数)。 服务器端将远程服务绑定到某个端口,进行TCP/IP监听(例如监听地址为rmi://127.0.0.1:1099)。 客户端与服务器建立TCP/IP连接(当然事先要知道服务器端的监听地址),按照接口声明的方法发送数据(可序列化的Java对象)以及要调用的服务名、方法名等。 服务器端将接收到的数据(字节流)反序列化,得到要调用的方法和参数信息;然后服务器端进行本地计算(方法调用)。 服务器端将计算的结果(可序列化的Java对象)发送给客户端。 客户端从接收到的返回数据(字节流)中进行反序列化,得到运算结果。 客户端断开与服务器端的TCP/IP连接,远程调用结束。2 Spring中RMI的使用
开始下面的步骤之前,我们要从Spring的网站下载开发所需要的jar包(实现RMI的部分的包在org.springframework.remoting.rmi中)。
2.1 服务器端开发
声明要发布为RMI服务的接口package demo.rmi.server;
?
/**
?* The purpose of this class is to define all presence method
?*
?*/
public interface IPresence {
????? /**
????? ?* subscribe presence info for the watcher
????? ?*
????? ?* @param watcherUri
????? ?* @param presentities
????? ?*/
????? public void subscribePresence(String watcherUri, String[] presentities);
?
}
?
?????? 实现要发布为RMI服务的接口
package demo.rmi.server;
?
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
?
/**
?* The purpose of this class is to implment presence operation
?*/
public class PresenceImpl implements IPresence {
?
????? private static Logger log = LoggerFactory.getLogger(PresenceImpl.class);
?
????? public void subscribePresence(String watcherUri, String[] presentities) {
??????????? if ((watcherUri == null) || (presentities == null)) {
????????????????? log.warn("watcherUri or presentities is null!");
????????????????? return;
??????????? }
??????????? if (log.isInfoEnabled()) {
????????????????? StringBuilder s = new StringBuilder();
????????????????? if (presentities != null) {
??????????????????????? for (String str : presentities) {
????????????????????????????? s.append(str).append(" ");
??????????????????????? }
????????????????? }
????????????????? log.info("subscribe presence for watcher:{}, presentities:{}",
????????????????????????????? watcherUri, s);
??????????? }
????? }
}
发布自己的RMI服务首先在Spring配置文件中(这里我命名为rmi-server.xml),配置所需要的Bean。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
??? <bean id="presenceService" />
?
??? <!-- define a RMI service listening at port 1001 -->
??? <bean id="serviceExporter_1001" />
??????? </property>
??????? <property name="serviceName">
???? ???????<value>presenceService</value>
??????? </property>
??????? <property name="serviceInterface">
??????????? <value>demo.rmi.server.IPresence</value>
??????? </property>
??????? <!-- defaults to 1099 -->
??????? <property name="registryPort" value="1001" />
??? </bean>
</beans>
?
然后启动我们的RMI服务,进行绑定和监听。
package demo.rmi.server;
?
import java.rmi.RemoteException;
?
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.remoting.rmi.RmiServiceExporter;
?
/**
?* The purpose of this class is to represent a rmi server via spring remoting
?* support
?*
?*/
public class RMIServer {
?
??????????? private static Logger log = LoggerFactory.getLogger(RMIServer.class);
?
??????????? /**
??????????? ?* start server by hard code
??????????? ?*/
??????????? public void startByAPI() {
??????????????????????? RmiServiceExporter exporter = new RmiServiceExporter();
??????????????????????? try {
??????????????????????????????????? exporter.setServiceInterface(IPresence.class);
??????????????????????????????????? exporter.setServiceName("serviceByAPI");
?
??????????????????????????????????? exporter.setService(new PresenceImpl());
??????????????????????????????????? exporter.setRegistryPort(1001);
?
??????????????????????????????????? exporter.afterPropertiesSet();
??????????????????????? } catch (RemoteException e) {
??????????????????????????????????? log.error("error when export service", e);
??????????????????????? }
??????????? }
?
??????????? /**
??????????? ?* start server by configuration in bean.xml
??????????? ?*/
??????????? public void startByCfg() {
??????????????????????? ApplicationContext context = new ClassPathXmlApplicationContext(
??????????????????????????????????????????????? "rmi-server.xml");
??????????????????????? if (log.isInfoEnabled()) {
??????????????????????????????????? log.info("application context 's display name :{}", context
??????????????????????????????????????????????????????????? .getDisplayName());
??????????????????????????????????? log.info("RMI server initialized successfully!");
??????????????????????? }
??????????? }
?
??????????? /**
??????????? ?* main method for start a rmi server
??????????? ?*
??????????? ?* @param args
??????????? ?*/
??????????? public static void main(String[] args) {
??????????????????????? // new RMIServer().startByAPI();
??????????????????????? new RMIServer().startByCfg();
??????????? }
?
}
当我们初始化Spring的ApplicationContext后,Spring会自动完成RMI服务的绑定和监听。
2.2 客户端开发
首先在Spring配置文件中(这里我命名为rmi-client.xml),配置所需要的Bean。
<?xml version="1.0" encoding="UTF-8"?>
<beans>
??? <!-- define a RMI client service which send to port 1001 -->
??? <bean id="prensenceServiceProxy_1001" };
?
??????????????????????? StringBuilder presentitiesInfo = new StringBuilder();
??????????????????????? for (String str : presentities) {
??????????????????????????????????? presentitiesInfo.append(str).append(" ");
??????????????????????? }
?
??????????????????????? if (log.isInfoEnabled()) {
??????????????????????????????????? log.info("now start send subscribe presnece request for watcher:{}"
??????????????????????????????????????????????????????????? + " ,presentities:{}", watcher, presentitiesInfo);
??????????????????????? }
??????????????????????? service.subscribePresence(watcher, presentities);
??????????? }
?
}
?
大家可以注意到,我分别在服务器端和客户端放入了使用Spring API动态(即不在Spring配置文件中固定配置)进行RMI监听和调用的代码,可供需要时参考。