時髦的18章:Distributed Computing: RMI with a dash of servlets, EJB, and Jini

這是深入淺出 Java 程式設計 第二版18章 分散式運算 遠端部署的RMI,這本書已經到了尾聲了,最後這兩章真是精彩,ㄚ琪覺得非常地受用,所以繼續破例分享這一章。

建構遠端服務

Step 1:建構Remote interface
遠端的interface定義了用戶端可以遠端呼叫的method。它是個作為服務的多型化class。stub與服務都會實做此interface!

Step 2:實做Remote
這是真正執行的class。它實做出定義在該interface上的method。它是用戶端會呼叫的物件。

Step 3:以rmic產生stub與skeleton
用戶端與伺服器都有helper。你無須建構這些class或產生這些class的原始碼。這都會在你執行JDK所附的rmic工具時自動的處理掉。
Step 4:啟動RMI registry(rmiregistry)
rmiregistry就像是電話簿。使用者會從此處取得proxy(用戶端的stub/helper)。

Step 5:啟動遠端服務
你必須服務物件開始執行。實做服務的class會起始服務的實體並向RMI registry登記。要有登記才能對用戶提供服務。

這些真是金字良句啊,應該很多都不懂吧。繼續看下去…

Step 1:建構Remote interface

①Extend過java.rmi.Remote
Remote是個標記性的interface,意味著沒有method。然而它對RMI有特殊的意義,所以你必須遵守這項規則。注意的這裡用的是extend,interface是可以extend過其他的interface。
public interface MyRemote extends Remote {

②宣告所有的method都會拋出RemoteException
import java.rmi.*;//Remote 在java.rmi中
public interface MyRemote extends Remote {
public String sayHello() throws RemoteException
}

③確定參數與回傳值都是primitive或Serializable
如果使用的是API中像是String、primitive等主要的型別(包括陣列與集合),就沒問題。如果是自訂的型別,那你就得要實做Serializable。
public String sayHello() throws RemoteException;

Step 2:實做Remote

①實做Remote這個interface
你的服務必需要實做Remote – 就是用戶端會呼叫的method。
public class MyRemoteImpl extends UniCastRemoteObject implements MyRemote {
public String sayHello() {
return “Server says, ‘Hey'”;
}
}

②extend過UnicastRemoteObject
public class MyRemoteImpl extends UniCastRemoteObject implements MyRemote {

③撰寫宣告RemoteException的無參數constructor
public MyRemoteImpl throws RemoteException {}

④向RMI registry登記服務
有了遠端服務,還必需要讓遠端用戶存取。這可以透過將它初始化並加進RMI registry。當你登記物件時,RMI系統會把stub加到registry中,因為這是用戶端所需要的。使用java.rmi.Naming的rebind()來登記服務。
try {
MyRemote service = new MyRemoteImpl();
Naming.rebind(“Remote Hello”,service);
} catch(Exception ex) {…}

Step 3:產生stub與skeleton

①對實做出的class(非interface)執行rmic
伴隨Java Software Development Kit而來的rmic工具會以服務的實做產生兩個新的class:stub與skeleton。它會依照命名規則在你的遠端實做名稱後面加上_Stub或_Skeleton。rmic有幾個選項,包括了不產生skeleton、觀察產出class的原始碼、或使用IIOP作為通訊協定等。在此使用一般的方式。產出的class會放在目前目錄下。要記住rmic必須能夠找到你所實做的class,因此你或許要從實做所在的目錄來執行rmic。

Step 4:啟動RMI registry

①叫出命令來啟動rmiregistry
要確定你是從可以存取到該class的目錄來啟動。最簡單的方法就是從classes這個目錄來跑。

Step 5:啟動遠端服務

①叫出另一個命令列來啟動服務
這可能是從你所實做的class上的main()或獨立的啟動用class來進行。在這個簡單的範例中,把啟動程式碼放在class的實作中,它的main()會將物件初始化並把它登記給RMI registry。

用戶端如何取得stub物件?

①用戶端查詢RMI registry
Naming.lookup(“rmi://127.0.0.1/Remote Hello”);

②RMI registry傳回stub物件
且RMI會自動的將stub解序列化。你必須要有rmic所產生的stub class,否則用戶端的stub不會被解序列化。

③用戶端就像取用真正的服務一樣的叫用stub上的method

確定每台機器都有所須的class檔案

使用RMI時程式設計師最常犯的三個錯:

1)忘記在啟動遠端服務前啟動rmiregistry(使用Naming.rebind()登記服務前rmiregistry必須啟動!)

2)忘記把參數與回傳型別做成可序列化(編譯器不會偵測到,執行時才會發現)

3)忘記將stub的class交給用戶端

ㄚ琪在實做時,在執行rmiregistry時發生:

Warning: JIT compiler “symcjit” not found. Will use interpreter.
security properties not found. using defaults.

這樣的錯誤,後來查到要把C:Program FilesJavajdk1.6.0_29bin加到PATH變數最前面,這是因為還有其它的Java執行環境所干擾,這樣做可以避免錯誤

在執行MyRemoteImpl這支程式時,會發生這樣的錯誤:

java.net.MalformedURLException: invalid URL String: Remote Hello
at java.rmi.Naming.parseURL(Naming.java:226)
at java.rmi.Naming.rebind(Naming.java:154)
at MyRemoteImpl.main(MyRemoteImpl.java:12)
Caused by: java.net.URISyntaxException: Illegal character in path at index 6: Re
mote Hello
at java.net.URI$Parser.fail(URI.java:2809)
at java.net.URI$Parser.checkChars(URI.java:2982)
at java.net.URI$Parser.parseHierarchical(URI.java:3066)
at java.net.URI$Parser.parse(URI.java:3024)
at java.net.URI.<init>(URI.java:578)
at java.rmi.Naming.intParseURL(Naming.java:256)
at java.rmi.Naming.parseURL(Naming.java:220)
… 2 more

一開始還真看不懂這是什麼錯誤?一直在猜,後來讀到Illegal character in path at index 6: Remote Hello
嗯,第6個字是空格,空格不符合語法,ㄚ琪就在猜不要用空格看看,在MyRemoteImpl.java裡的Remote Hello改成Remote_Hello,Yes,行!另外在MyRemoteClient.java裡

MyRemote service = (MyRemote) Naming.lookup(“rmi://127.0.0.1/Remote Hello”);

也改成

MyRemote service = (MyRemote) Naming.lookup(“rmi://127.0.0.1/Remote_Hello”);

沒錯,這樣子就對了,看來不允許空格的字元,這是目前使用jdk1.6.0_29會有這樣的問題,請各位注意。

建構與執行servlet的步驟

Step 1:找出可以放servlet的地方

Step 2:取得servlets.jar並加到classpath上

Step 3:經由extend過HttpServlet來撰寫servlet的class
public class MyServletA extends HttpServlet {…}

Step 4:撰寫HTML來叫用servlet

Step 5:設定HTML網頁與servlet給伺服器

呼,過去的就讓它過去吧,終於讀完了,後面雖然還有很多附錄、很多程式碼,但是我想ㄚ琪自己都可以解決,很高興又看完了一本巨作,這一本很讚,值得一讀。

感謝你看到這裡,很快就可以離開了,但最好的獎勵行動就是按一下幫我分享或留言,感恩喔~

點我分享到Facebook

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *