分享

Spring中RMI调用方法

 击碎星辰 2010-07-05

Spring中RMI调用方法

1 RMI的概念

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./dtd/spring-beans-2.0.dtd">

<beans>

    <bean id="presenceService" class="demo.rmi.server.PresenceImpl" />

 

    <!-- define a RMI service listening at port 1001 -->

    <bean id="serviceExporter_1001" class="org.springframework.remoting.rmi.RmiServiceExporter">

        <property name="service">

            <ref bean="presenceService" />

        </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" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">

        <property name="serviceUrl">

            <value>rmi://127.0.0.1:1001/presenceService</value>

        </property>

        <property name="serviceInterface">

            <value>demo.rmi.server.IPresence</value>

        </property>

    </bean>

</beans>

然后我们可以编写客户端进行RMI调用的代码。

package demo.rmi.client;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

import demo.rmi.server.IPresence;

 

/**

 * The purpose of this class is to represent a RMI client

 */

public class RMIClient {

            private static Logger log = LoggerFactory.getLogger(RMIClient.class);

 

            /**

             * @param args

             */

            public static void main(String[] args) {

                        ApplicationContext context = new ClassPathXmlApplicationContext(

                                                "rmi-client.xml");

                        if (log.isInfoEnabled()) {

                                    log.info("application context 's display name :{}", context

                                                            .getDisplayName());

                                    log.info("RMI client initialized successfully!");

 

                        }

 

                        // test get a RMI client service via Spring API at runtime

                        // RmiProxyFactoryBean factory = new RmiProxyFactoryBean();

                        // factory.setServiceInterface(IPresence.class);

                        // factory.setServiceUrl("rmi://127.0.0.1:1002/presenceService");

                        // factory.afterPropertiesSet();

                        //

                        // IPresence service2 = (IPresence) factory.getObject();

                        //

                        // String[] wt = service2.getMyWatchers("sip:test@mycompany.com");

                        // System.out.println("service2 works fine,response watchers 's length:"

                        // + wt.length);

 

                        IPresence service = (IPresence) context

                                                .getBean("prensenceServiceProxy_1001");

                        String watcher = "sip:alice@mycompany.com";

                        String[] presentities = new String[] { "sip:bob@ mycompany.com",

                                                "sip:susan@mycompany.com" };

 

                        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监听和调用的代码,可供需要时参考。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多