RMI的概念
RMI(Remote Method Invocation)遠程方法調用是一種計算機之間利用遠程對象互相調用實現雙方通訊的一種通訊機制。使用這種機制,某一臺計算機上的對象可以調用另外一臺計算機上的對象來獲取遠程數據。RMI是Enterprise JavaBeans的支柱,是建立分布式Java應用程序的方便途徑。在過去,TCP/IP套接字通訊是遠程通訊的主要手段,但此開發方式沒有使用面向對象的方式實現開發,在開發一個如此的通訊機制時往往令程序員感覺到乏味,對此RPC(Remote Procedure Call)應運而生,它使程序員更容易地調用遠程程序,但在面對復雜的信息傳訊時,RPC依然未能很好的支持,而且RPC未能做到面向對象調用的開發模式。針對RPC服務遺留的問題,RMI出現在世人面前,它被設計成一種面向對象的通訊方式,允許程序員使用遠程對象來實現通信,并且支持多線程的服務,這是一次遠程通訊的革命,為遠程通信開辟新的里程碑。
RMI的開發步驟
先創建遠程接口及聲明遠程方法,注意這是實現雙方通訊的接口,需要繼承Remote
開發一個類來實現遠程接口及遠程方法,值得注意的是實現類需要繼承UnicastRemoteObject
通過javac命令編譯文件,通過java -server 命令注冊服務,啟動遠程對象
最后客戶端查找遠程對象,并調用遠程方法
簡單實例
首先為服務建立一個Model層,注意因為此對象需要現實進行遠程傳輸,所以必須繼承Serializable
package rmi.model; import java.io.Serializable; //注意對象必須繼承Serializable publicclass PersonEntity implements Serializable { privateint id; private String name; privateint age; publicvoid setId(int id) { this.id = id; } publicint getId() { return id; } publicvoid setName(String name) { this.name = name; } public String getName() { return name; } publicvoid setAge(int age) { this.age = age; } publicint getAge() { return age; } } |
創建遠程接口PersonService,注意遠程接口需要繼承Remote
package rmi.service; import java.rmi.Remote; import java.rmi.RemoteException; import java.util.List; import rmi.model.*; //此為遠程對象調用的接口,必須繼承Remote類 public interface PersonService extends Remote { public List<PersonEntity> GetList() throws RemoteException; } |
建立PersonServiceImpl實現遠程接口,注意此為遠程對象實現類,需要繼承UnicastRemoteObject
package rmi.serviceImpl; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.LinkedList; import java.util.List; import rmi.model.PersonEntity; import rmi.service.*; //此為遠程對象的實現類,須繼承UnicastRemoteObject public class PersonServiceImpl extends UnicastRemoteObject implements PersonService { public PersonServiceImpl() throws RemoteException { super(); // TODO Auto-generated constructor stub } public List<PersonEntity> GetList() throws RemoteException { // TODO Auto-generated method stub System.out.println("Get Person Start!"); List<PersonEntity> personList=new LinkedList<PersonEntity>(); PersonEntity person1=new PersonEntity(); person1.setAge(25); person1.setId(0); person1.setName("Leslie"); personList.add(person1); PersonEntity person2=new PersonEntity(); person2.setAge(25); person2.setId(1); person2.setName("Rose"); personList.add(person2); return personList; } } |
建立服務器端,在服務器端注冊RMI通訊端口與通訊路徑,然后通訊javac命令編譯文件,通過java -server 命令注冊服務。以下面代碼為例,如果閣下將項目建立于D:\\RMI\RemotingService文件夾上時,則先輸入D:\\RMI\RemotingService\src>javac rmi/remotingservice/Program.java獲取Program.class(如何閣下使用的MyEclipse等開發工具,可跳過此步,直接在*/bin文件夾中直接調用已經生成的Program.class),然后輸入D:\\RMI\RemotingService\src>java rmi/remotingservice/Program啟動服務。
package rmi.remotingservice; import java.rmi.Naming; import java.rmi.registry.LocateRegistry; import rmi.service.*; import rmi.serviceImpl.*; public class Program{ public static void main(String[] args) { try { PersonService personService=new PersonServiceImpl(); //注冊通訊端口 LocateRegistry.createRegistry(6600); //注冊通訊路徑 Naming.rebind("rmi://127.0.0.1:6600/PersonService", personService); System.out.println("Service Start!"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } |
最后建立客戶端進行測試,注意客戶調用的RMI路徑必須服務器配置一致
package rmi.remotingclient; import java.rmi.Naming; import java.util.List; import rmi.model.PersonEntity; import rmi.service.*; public class Program { public static void main(String[] args){ try{ //調用遠程對象,注意RMI路徑與接口必須與服務器配置一致 PersonService personService=(PersonService)Naming.lookup("rmi://127.0.0.1:6600/PersonService"); List<PersonEntity> personList=personService.GetList(); for(PersonEntity person:personList){ System.out.println("ID:"+person.getId()+" Age:"+person.getAge()+" Name:"+person.getName()); } }catch(Exception ex){ ex.printStackTrace(); } } } |
常見錯誤
在命令提示符調用java命令時,顯示并無此命令。這是因為未在“環境變量”中綁定JAVA的JDK命令造成的,你首先單擊“計算機右鍵”->“屬性”->“高級”->“環境變量”。在系統變量Path設置中加載為JDK的路徑 .;D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\bin。然后在ClassPath加載服務器端的Program.class地址 .;D:\\RMI\RemotingService\bin
在調用javac命令時出現“javac 找不到文件 ..... ”此錯誤,可能是因為閣下輸入的文件路徑出現錯誤造成,注意不要把D:\\RMI\RemotingService\src>javac rmi/remotingservice/Program.java寫錯為D:\\RMI\RemotingService\src>javac rmi.remotingservice.Program.java
在調用D:\\RMI\RemotingService\bin>java rmi/remotingservice/Program命令時出現“Exception in thread 'main' java.lang.NoClassEdfoundError”錯誤,第一這可能是閣下把Program錯寫為Program.class,注意java命令不需要加后綴名。第二可能是閣下把“java rmi/remotingservice/Program”錯寫為“java rmi\remotingservice\Program"。