這是深入淺出 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給伺服器
呼,過去的就讓它過去吧,終於讀完了,後面雖然還有很多附錄、很多程式碼,但是我想ㄚ琪自己都可以解決,很高興又看完了一本巨作,這一本很讚,值得一讀。