天天看點

Java RMI技術以及Spring封裝了的RMI技術

    最近應用到了Java RMI技術,是以總結一下RMI的使用,另外EJB的實作也是以Java RMI為基礎核心的。RMI遠端方法調用,可以跨機器通過網絡調用,不過Java RMI隻支援兩邊都是Java程式,如果要實作完全兩邊異構,那麼就要用到傳說中的Web Service了。為了看好效果,都要建立兩個或兩個以上工程,當然,如果你有兩個機器并通過區域網路相連更好,如果能同有網際網路的條件就更好了,以下是同一機器不同工程的實驗。

Java RMI

首先建立一個工程,随便什麼工程,為了友善,就Java Project吧。

1、建立一個接口,繼承Remote

[java]  view plain copy

  1. package leon.rmi.iface;  
  2. import java.rmi.Remote;  
  3. import java.rmi.RemoteException;  
  4. public interface IHello extends Remote {   
  5.     public String sayHello(String name) throws RemoteException;   
  6.     public int sum(int a, int b)throws RemoteException;  
  7. }  

2、建立接口的實作類

[java]  view plain copy

  1. package leon.rmi.impl;  
  2. import java.rmi.RemoteException;  
  3. import java.rmi.server.UnicastRemoteObject;  
  4. import leon.rmi.iface.IHello;  
  5. public class HelloImpl extends UnicastRemoteObject implements IHello {  
  6.     private static final long serialVersionUID = 1L;  
  7.     public HelloImpl() throws RemoteException {  
  8.         super();  
  9.     }  
  10.     @Override  
  11.     public String sayHello(String name) throws RemoteException {  
  12.         return "Welcome, " + name;  
  13.     }  
  14.     @Override  
  15.     public int sum(int a, int b) throws RemoteException{  
  16.         return a + b;  
  17.     }  
  18. }  

說明:接口的實作類同時要實作Serializable接口,這裡繼承UnicastRemoteObject也是間接實作Serializable接口,同時,因為構造方法需要抛出RemoteException,是以不能預設使用隐含的無參構造方法,而應該自己顯式定義構造方法。

3、建立應用類,注冊和啟動服務端RMI,以被用戶端調用

[java]  view plain copy

  1. package leon.rmi.impl;  
  2. import java.net.MalformedURLException;  
  3. import java.rmi.AlreadyBoundException;  
  4. import java.rmi.Naming;  
  5. import java.rmi.RemoteException;  
  6. import java.rmi.registry.LocateRegistry;  
  7. import leon.rmi.iface.IHello;  
  8. public class HelloServer {  
  9.     public static void main(String args[]) {  
  10.         try {  
  11.             //建立一個遠端對象  
  12.             IHello rhello = new HelloImpl();      
  13.             //生成遠端對象系統資料庫Registry的執行個體,并指定端口為8888(預設端口是1099)  
  14.             LocateRegistry.createRegistry(8888);  
  15.             //把遠端對象注冊到RMI注冊伺服器上,并命名為RHello  
  16.             //綁定的URL标準格式為:rmi://host:port/name(協定名可以省略,下面兩種寫法都可以)  
  17.             Naming.bind("rmi://10.225.112.86:8888/RHello", rhello);  
  18.             //Naming.bind("//10.225.112.86:8888/RHello",rhello);  
  19.             System.out.println(">>INFO:遠端IHello對象綁定成功!");  
  20.         } catch (RemoteException e) {  
  21.             System.out.println("建立遠端對象發生異常!");  
  22.             e.printStackTrace();  
  23.         } catch (AlreadyBoundException e) {  
  24.             System.out.println("發生重複綁定對象異常!");  
  25.             e.printStackTrace();  
  26.         } catch (MalformedURLException e) {  
  27.             System.out.println("發生URL畸形異常!");  
  28.             e.printStackTrace();  
  29.         }  
  30.     }  
  31. }  

說明:綁定的位址10.225.112.86是我的區域網路位址可以在DOS指令行用ipconfig檢視,如果你的機器沒有任何聯網,可以使用127.0.0.1或localhost。

運作HelloServer.java看到,紅色方塊顯示正在運作:

        >>INFO:遠端IHello對象綁定成功!

好了,現在遠端服務提供端建立完成,下面建立用戶端。

建立一個新的工程,為了友善,也是Java Project吧,

1、 因為用戶端需要有服務端那邊提供的接口,才可以通路,是以要将服務端的IHello接口完全拷貝(連同包)到用戶端,當然為了友善,你在用戶端工程中建立一個完全一樣的接口也可以。實際運用中通常是要服務端接口打成jar包來提供的。

2、 建立用戶端調用類

[java]  view plain copy

  1. package testrmi;  
  2. import java.rmi.Naming;  
  3. import leon.rmi.iface.IHello;  
  4. public class HelloClient {  
  5.     public static void main(String args[]) {  
  6.         try {  
  7.             // 在RMI服務系統資料庫中查找名稱為RHello的對象,并調用其上的方法  
  8.             IHello rhello = (IHello) Naming.lookup("rmi://10.225.112.86:8888/RHello");  
  9.             System.out.println(rhello.sayHello("水哥"));  
  10.             System.out.println(rhello.sum(454, 5457));  
  11.         } catch (Exception e) {  
  12.             e.printStackTrace();  
  13.         }  
  14.     }  
  15. }  

運作,顯示,成功。

呵呵,是不是很簡單?對吧。

下面我們要使用Spring封裝的Java RMI技術,也是很多項目都會用到的。後面我有個Spring RMI的例子。要看懂下面Spring的例子,你需要已經會用Spring,會配置Spring,否則怕你看不懂,是以如果還不懂Spring的,先學學Spring,入下門吧。

Spring RMI

       Spring RMI中,主要有兩個類:org.springframework.remoting.rmi.RmiServiceExporter和org.springframework.remoting.rmi.RmiProxyFactoryBean

服務端使用RmiServiceExporter暴露RMI遠端方法,用戶端用RmiProxyFactoryBean間接調用遠端方法。

   首先,也是兩個工程,服務端用Web工程,因為使用Spring,我們依托Web容器來完成。

1、在該服務端Web工程中添加接口,普通接口,無需繼承其他

[java]  view plain copy

  1. package leon.rmi.iface;  
  2. public interface IUserDao {  
  3.     public String getUserList();  
  4.     public int sum(int a, int b);  
  5. }  

  2、接口的實作類

[java]  view plain copy

  1. package leon.rmi.impl;  
  2. import leon.rmi.iface.IUserDao;  
  3. public class UserDaoImpl implements IUserDao {  
  4.     @Override  
  5.     public String getUserList() {  
  6.         return "Hello,Get the user list from database!";  
  7.     }  
  8.     @Override  
  9.     public int sum(int a, int b) {  
  10.         return a+b;  
  11.     }  
  12. }  

3、在該服務端Web工程中添加Spring的bean配置檔案,比如命名為rmi.xml,内容如下:

[html]  view plain copy

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans:beans xmlns="http://www.springframework.org/schema/security"  
  3.     xmlns:beans="http://www.springframework.org/schema/beans"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  7.     http://www.springframework.org/schema/security  
  8.     http://www.springframework.org/schema/security/spring-security-3.0.xsd">  
  9.     <beans:bean id="userDaoRmi" class="leon.rmi.impl.UserDaoImpl">   
  10.     </beans:bean>   
  11.     <beans:bean id="userSvcExporter" class="org.springframework.remoting.rmi.RmiServiceExporter">   
  12.         <beans:property name="service" ref="userDaoRmi"/>   
  13.         <beans:property name="serviceName" value="userDaoService"/>   
  14.         <beans:property name="serviceInterface" value="leon.rmi.iface.IUserDao"/>   
  15.         <beans:property name="registryPort" value="9111"/>   
  16.         <beans:property name="servicePort" value="10023"/>   
  17.     </beans:bean>   
  18. </beans:beans>  

   說明:這裡不詳細的說明了,主要配置了真實實作類,用RmiServiceExporter暴露時,配置property要注意的有service,serviceName,serviceInterface,端口registryPort。

   啟動Web工程的伺服器,該配置檔案應該被Spring的監聽器監聽,并加載,啟動成功後,服務端就算建好了。如果伺服器是在localhost啟動的,那麼暴露的RMI的IP也是localhost,如果需要使用其他IP,需要讓伺服器在其他的IP啟動。

好了,吃完午飯繼續寫

用戶端調用

為了友善也隻建立一個簡單的Java Project,使用靜态的java代碼來調用了。

1、 在源檔案src下建立一個springbeans.xml

[html]  view plain copy

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans:beans xmlns="http://www.springframework.org/schema/security"  
  3.     xmlns:beans="http://www.springframework.org/schema/beans"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  7.     http://www.springframework.org/schema/security  
  8.     http://www.springframework.org/schema/security/spring-security-3.0.xsd">  
  9.     <beans:bean id="userDaoProxy" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">   
  10.         <beans:property name="serviceUrl" value="rmi://localhost:9111/userDaoService"/>   
  11.         <beans:property name="serviceInterface" value="leon.rmi.iface.IUserDao"/>   
  12.     </beans:bean>  
  13. </beans:beans>  

這裡注意到RmiProxyFactoryBean的兩個重要的property:serviceUrl和serviceInterface,IUserDao接口可以從服務端的接口打成jar包來提供。

2、 建立java類

[java]  view plain copy

  1. package testrmi;  
  2. import leon.rmi.iface.IUserDao;  
  3. import org.springframework.context.ApplicationContext;  
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  5. public class TestRMI2 {  
  6.     public static void main(String[] args) {  
  7.          ApplicationContext ctx = new ClassPathXmlApplicationContext("springbeans.xml");  
  8.          IUserDao userDao = (IUserDao) ctx.getBean("userDaoProxy");  
  9.          System.out.println(userDao.getUserList());  
  10.          System.out.println(userDao.sum(145, 487));  
  11.     }  
  12. }  

運作,成功。

好了,這就是一個采用Spring封裝的RMI的例子,項目工作中應該經常使用的。

RMI