RMI的本質就是實現在不同JVM之間的調用,它的實現方法就是在兩個JVM中各開一個Stub和Skeleton,二者通過socket通信來實現參數和返回值的傳遞。
???? 有關RMI的例子代碼網上可以找到不少,但絕大部分都是通過extend the interface java.rmi.Remote實現,已經封裝的很完善了,不免使人有霧里看花的感覺。下面的例子是我在《Enterprise JavaBeans》里看到的,雖然很粗糙,但很直觀,利于很快了解它的工作原理。
Ⅰ:RMI工作原理(自定義實現一個Stub 和 Skeleton)
1. 定義一個Person的接口,其中有兩個business method, getAge() 和getName()
Person代碼:
?
public?interface?Person?{??? ??????public?int?getAge()?throws?Throwable;??? ??????public?String?getName()?throws?Throwable;??? ??}?
?
2. Person的實現PersonServer類
PersonServer代碼:
?
public?class?PersonServer?implements?Person?{??? ??????private?int?age;??? ??????private?String?name;??? ??????public?PersonServer(String?name,?int?age)?{??? ??????????this.age?=?age;??? ??????????this.name?=?name;??? ??????}??? ??????public?int?getAge()?{??? ??????????return?age;??? ??????}??? ??????public?String?getName()?{??? ??????????return?name;??? ??????}??? ??}??????
3. 好,我們現在要在Client機器上調用getAge()和getName()這兩個business method,那么就得編寫相應的Stub(Client端)和Skeleton(Server端)程序。這是Stub的實現:
Person_Stub代碼:
//存根(stub)Person_Stub的實現:
?
import?java.io.ObjectOutputStream;??? ??import?java.io.ObjectInputStream;??? ??import?java.net.Socket;??? ??public?class?Person_Stub?implements?Person?{??? ??????private?Socket?socket;??? ??????public?Person_Stub()?throws?Throwable?{??? ??????????//?connect?to?skeleton??? ??????????socket?=?new?Socket("computer_name",?9000);??? ??????}??? ??????public?int?getAge()?throws?Throwable?{??? ??????????//?pass?method?name?to?skeleton??? ??????????ObjectOutputStream?outStream?=??? ??????????????new?ObjectOutputStream(socket.getOutputStream());??? ??????????outStream.writeObject("age");??? ??????????outStream.flush();??? ??????????ObjectInputStream?inStream?=??? ??????????????new?ObjectInputStream(socket.getInputStream());??? ??????????return?inStream.readInt();??? ??????}??? ??????public?String?getName()?throws?Throwable?{??? ??????????//?pass?method?name?to?skeleton??? ??????????ObjectOutputStream?outStream?=??? ??????????????new?ObjectOutputStream(socket.getOutputStream());??? ??????????outStream.writeObject("name");??? ??????????outStream.flush();??? ??????????ObjectInputStream?inStream?=??? ??????????????new?ObjectInputStream(socket.getInputStream());??? ??????????return?(String)inStream.readObject();??? ??????}??? ??}??????
注意,Person_Stub和PersonServer一樣,都implements Person。它們都實現了getAge()和getName()兩個business method,不同的是PersonServer是真的實現,Person_Stub是建立socket連接,并向Skeleton發請求,然后通過Skeleton調用PersonServer的方法,最后接收返回的結果。
4. 骨架(Skeleton)的實現
Person_Skeleton代碼:
?
import?java.io.ObjectOutputStream;??? ??import?java.io.ObjectInputStream;??? ??import?java.net.Socket;??? ??import?java.net.ServerSocket;??? ??public?class?Person_Skeleton?extends?Thread?{??? ??????private?PersonServer?myServer;??? ??????public?Person_Skeleton(PersonServer?server)?{??? ??????????//?get?reference?of?object?server??? ??????????this.myServer?=?server;??? ??????}??? ??????public?void?run()?{??? ??????????try?{??? ??????????????//?new?socket?at?port?9000??? ??????????????ServerSocket?serverSocket?=?new?ServerSocket(9000);??? ??????????????//?accept?stub's?request??? ??????????????Socket?socket?=?serverSocket.accept();??? ??????????????while?(socket?!=?null)?{??? ??????????????????//?get?stub's?request??? ??????????????????ObjectInputStream?inStream?=??? ??????????????????????new?ObjectInputStream(socket.getInputStream());??? ??????????????????String?method?=?(String)inStream.readObject();??? ??????????????????//?check?method?name??? ??????????????????if?(method.equals("age"))?{??? ??????????????????????//?execute?object?server's?business?method??? ??????????????????????int?age?=?myServer.getAge();??? ??????????????????????ObjectOutputStream?outStream?=??? ??????????????????????????new?ObjectOutputStream(socket.getOutputStream());??? ??????????????????????//?return?result?to?stub??? ??????????????????????outStream.writeInt(age);??? ??????????????????????outStream.flush();??? ??????????????????}??? ??????????????????if(method.equals("name"))?{??? ??????????????????????//?execute?object?server's?business?method??? ??????????????????????String?name?=?myServer.getName();??? ??????????????????????ObjectOutputStream?outStream?=??? ??????????????????????????new?ObjectOutputStream(socket.getOutputStream());??? ??????????????????????//?return?result?to?stub??? ??????????????????????outStream.writeObject(name);??? ??????????????????????outStream.flush();??? ??????????????????}??? ??????????????}??? ??????????}?catch(Throwable?t)?{??? ??????????????t.printStackTrace();??? ??????????????System.exit(0);??? ??????????}??? ??????}??? ??????public?static?void?main(String?args?[])?{??? ??????????//?new?object?server??? ??????????PersonServer?person?=?new?PersonServer("Richard",?34);??? ??????????Person_Skeleton?skel?=?new?Person_Skeleton(person);??? ??????????skel.start();??? ??????}??? ??}?? ????
Skeleton類 extends from Thread,它長駐在后臺運行,隨時接收client發過來的request。并根據發送過來的key去調用相應的business method。
5. 最后一個,Client的實現
PersonClient 代碼:
?
public?class?PersonClient?{??? ??????public?static?void?main(String?[]?args)?{??? ??????????try?{??? ??????????????Person?person?=?new?Person_Stub();??? ??????????????int?age?=?person.getAge();??? ??????????????String?name?=?person.getName();??? ??????????????System.out.println(name?+?"?is?"?+?age?+?"?years?old");??? ??????????}?catch(Throwable?t)?{??? ??????????????t.printStackTrace();??? ??????????}??? ??????}??? ??}???????
Client(PersonClient)的本質是,它要知道Person接口的定義,并實例一個Person_Stub,通過Stub來調用business method,至于Stub怎么去和Server溝通,Client就不用管了。
注意它的寫法:
Person person = new Person_Stub();而不是Person_Stub person = new Person_Stub();為什么?因為要面向接口編程嘛,呵呵。
//RMI實質上就是生成2個類stub,skeleton來進行參數和返回值的傳遞,采用值傳遞方式
//類似于以前寫的聊天室程序,被傳遞的對象應實現java.io.Serializable接口
轉載于:https://www.cnblogs.com/yin-jingyu/archive/2012/06/14/2549361.html
總結
以上是生活随笔為你收集整理的stub 和 skeleton 的讲解,自己实现一个stub和skeleton程序的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。