遠端呼叫 - spring+rmi

maqianmaqian發表於2010-09-26

Spring提供類用於整合各種遠端訪問技術。這種對遠端訪問的支援可以降低你在用POJO實現支援遠端訪問業務時的開發難度。目前,Spring提供對下面四種遠端訪問技術的支援:

遠端方法呼叫(RMI)。通過使用RmiProxyFactoryBeanRmiServiceExporter,Spring支援傳統的RMI(使用java.rmi.Remote interfaces 和 java.rmi.RemoteException)和通過RMI呼叫器(可以使用任何Java介面)的透明遠端呼叫。

Spring的HTTP呼叫器。Spring提供一種特殊的遠端呼叫策略支援任何Java介面(象RMI呼叫器一樣),它允許Java序列化能夠通過HTTP傳送。對應的支援類是HttpInvokerProxyFactoryBeanHttpInvokerServiceExporter

Hessian。通過使用HessianProxyFactoryBeanHessianServiceExporter,你可以使用Caucho提供的輕量級基於HTTP的二進位制協議透明地提供你的業務。

Burlap。Burlap是基於XML的,它可以完全代替Hessian。Spring提供的支援類有BurlapProxyFactoryBeanBurlapServiceExporter

JAX RPC (TODO).

RMI是不能夠穿越防火牆的,在網上也查了一些資料,但根據其提供的方法都沒有成功,唉,功夫不負有心人,經過一番努力,還是把它實現了,其實這東西就是一層窗紙,捅破了也沒有什麼太難得,廢話不說了,我們開始吧。(不好意思,還得再說一句廢話:得益於羅士飛的那本spring教程程式碼)。

 

在此之前,我先把目錄結構抓取個影象給大家看看。

當然首先要把spring的相關依賴的jar包引入了。這裡就不能描述了。

先寫伺服器段程式碼:
1. 定義介面 ILogPerson.java
package com.openv.spring;

public interface ILogPerson {
     public String getPersion(PersonVO personVO);
}

2. 定義POJO PersonVO.java
package com.openv.spring;

import java.io.Serializable;

public class PersonVO implements Serializable {
     private String firstname;
     private String lastname;

     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;
     }
}

注意:這裡的PersonVO.java 必須繼承Serializable 以實現序列化,不然會抱錯,謹記!


3. 定義實現:LogPerson.java
package com.openv.spring;

public class LogPerson implements ILogPerson{

     public String getPersion(PersonVO personVO) {
         return personVO.getFirstname()+" @#@ "+personVO.getLastname();  
     }
}

4. 定義spring的依賴注入的檔案appcontextrmiserver.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "
http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

<bean id="logPerson" class="com.openv.spring.LogPerson"/>

<bean id="logPersonService"
      class="org.springframework.remoting.rmi.RmiServiceExporter">
  <!-- RmiServiceExporter 對服務名沒有特殊要求 -->
   <property name="serviceName">
    <value>LogPerson</value>
   </property>
   <property name="service">
    <ref bean="logPerson"/>
   </property>
   <property name="serviceInterface">
    <value>com.openv.spring.ILogPerson</value>
   </property>
  <!-- 避免與預設的RMI註冊埠衝突,因此修改為1200 -->
   <property name="registryPort">
    <value>1200</value>
   </property>
</bean>

</beans>

5. 定義執行rmi服務的類: LogPersonRmiServer.java
package com.openv.spring;

import org.springframework.core.io.Resource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.beans.factory.BeanFactory;

import java.io.Serializable;

public class LogPersonRmiServer{
     public static void main(String[] args) {
         //初始化appcontextrmiserver.xml
         Resource sresource = new ClassPathResource("appcontextrmiserver.xml");
         BeanFactory sfactory = new XmlBeanFactory(sresource);

         //註冊RMI
         sfactory.getBean("logPersonService");

     }
}

執行main函式,rmi服務就啟動了。

下面寫客戶呼叫端的程式碼了。
大家從目錄圖中看一下,為了除錯方便,我把服務端和客戶端寫在了一起。在實際的專案中,客戶端的程式碼是不可能和伺服器端在一起的,那樣還叫什麼遠端呼叫呀,呵呵。在實際的專案中,我們應該把介面ILogPerson.java和POJO PersonVO.java 檔案打成jar包給客戶端引用即可,而實現是在伺服器端完成。

下面我們可以在另外一臺計算機(為了強調遠端嘛,呵呵)上新建立一個客戶端呼叫的工程。客戶端很簡單

1. 引入spring的依賴檔案和 介面ILogPerson.java和POJO PersonVO.java 檔案打成jar包

2. spring的依賴注入的檔案 appcontextrmiclient.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "
http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="LogPerson"
   class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
   <property name="serviceUrl"><value>rmi://77.20.64.237:1200/LogPerson</value></property>
   <property name="serviceInterface"><value>com.openv.spring.ILogPerson</value></property>
</bean>
</beans>

3. 呼叫檔案 LogPersonRmiClient.java
package com.openv.spring;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

public class LogPersonRmiClient {
     public static void main(String[] args) {
        //初始化appcontextrmiclient.xml
         Resource cresource = new ClassPathResource("appcontextrmiclient.xml");
         BeanFactory cfactory = new XmlBeanFactory(cresource);

        //例項化Person值物件
         PersonVO personVO = new PersonVO();
         personVO.setFirstname("Luo2");
         personVO.setLastname("Shifei");

        //獲得RMI服務
         ILogPerson clientLog = (ILogPerson) cfactory.getBean("LogPerson");

        //呼叫RMI服務
         System.out.println("==>> " + clientLog.getPersion(personVO));
     }
}
客戶端很簡單的,呵呵。看看執行結果吧。

雖然簡單,但是也有四五個檔案,其實每個檔案不是很複雜,只要耐著心思把其一個個寫出來,就能成功,如果執行結果出來了,你對rmi的各種疑惑也就形如冰釋了。我也搞了大半天才將其實現,願能給參看的朋友一些提示。

經過spring的封裝,rmi的複雜過程得到了很大的簡化,基本變成了配置的過程,什麼rmi手工註冊和聲成什麼亂七八糟的檔案都省略了。不過不能穿越防火牆,下面我們在介紹一種可以穿越防火牆的spring遠端呼叫hissian

轉載自: http://hi.baidu.com/wingis/blog/item/b12e538baa13f4d8fd1f1089.html/cmtid/792663112267db73cb80c433

 

相關文章