天天看點

學習JavaFX Script,第二部分:使用RMI進行遠端通信

       本系列的第一部分向Java程式員介紹了JavaFX腳本程式設計語言的文法及語義。本文在您對JavaFX腳本認知的基礎上進行描述,調用Java平台的遠端方法調用(Remote Method Invocation,Java RMI)類庫,使JavaFX圖形使用者界面(GUI)可以遠端通信。在JavaFX腳本中使用RMI是非常直接的,使用簡單快捷的方式就可以完成示範和測試用戶端-伺服器功能。

        在NetBeans中建立一個JavaFX腳本工程(Creating a JavaFX Script Project in the NetBeans IDE)

        1、從NetBeans的主菜單中選擇File菜單,接着選擇Net Project。

        2、在New Project向導對話框中,在Categories面闆中選擇General,在Project面闆中選擇Java Application。點選Next。

        3、在Project Name域中輸入JavaFXClient。

        4、在Project Location中,點選Browse,然後指定存儲工程的位置。

        5、取消對Set as Main Project和Create Main Class複選框的選擇,然後點選Finish。

        現在,使用IDE建立一個名為HelloServer的JavaFX Script檔案。

        1、在Projects視窗中,右鍵點選JavaFXClient > Source Packages節點,選擇New > File/Folder。

        2、在Categories面闆中,選擇Other,接着在File Types面闆中,選擇JavaFX File。然後點選Next。現在,當你在Projects視窗中調用主工程節點的New或者Source Packages節點時,JavaFX檔案類型應該出現在可用的檔案類型清單中。

        3、在New JavaFX File向導中的Name and Location頁中,File Name中輸入MyClient,Folder域中輸入src/client。注意,現在建立的檔案名會出現在Created File域中。

        4、點選Finish完成工程的建立。

        5、在Projects視窗中,右鍵點選JavaFXClient節點,選擇Properties。

        6、在Properties對話框的Categories面闆中,選擇Run。

        7、在Arguments域中輸入腳本的名稱:client.MyClient,點選OK。

        此時将會在JavaFXClient工程的client目錄中建立一個名為MyClient.fx的空JavaFX Script檔案。此時,讓這個檔案為空,接着設定項目的另外一部分——完成RMI伺服器的設定後将重新傳回這裡。

       使用遠端方法調用(RMI)進行用戶端--伺服器通信(Client-Server Communication with Remote Method Invocation(RMI))

        Java遠端方法調用(Java RMI)是用來實作遠端等價對象調用的Java應用程式接口(API)。使用RMI開發分布式程式比用socket要簡單,因為開發者不需要定義協定,而定義協定往往是消耗時間又容易出錯的工作。

        使用RMI,開發者有從本地類檔案調用本地方法的假象,其實,參數被發送到遠端目标并被解釋,然後結果又被發送回調用者。因為JavaFX Script可以調用Java對象,所有RMI就是一個讓JavaFX用戶端進行遠端通信的既快捷又簡單的工具。

        使用RMI開發一個分布式JavaFX Script程式包含一下步驟:

        在NetBeans中,按如下步驟操作:

        1、從File菜單中選擇New Project。應該可以看到類似圖1的一個對話框。

                       圖1  在NetBeans5.5.1 中建立一個工程

        2、在Categories清單中,選擇General。在Projects清單中,選擇Java Application。點選Next。應該可以看到一個類似圖2的對話框。

                   圖2  在NetBeans IDE中自定義新工程

        3、在Project Name中輸入JavaRMIServer。選擇适當的檔案夾儲存項目,然後取消對Set as Main Project的選擇。最後,點選Finish按鈕。這就建立了一個名為JavaRMIServer的Java工程。

        現在,在server包中建立一個名為ServerInterface的Java接口,如代碼示例1所示。接口ServerInterface包含了一個方法,ping(),它擷取一個String參數,傳回一個hello加上該參數組成的字元串。

        代碼示例1

學習JavaFX Script,第二部分:使用RMI進行遠端通信

package server;

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

import java.rmi.Remote;

學習JavaFX Script,第二部分:使用RMI進行遠端通信

import java.rmi.RemoteException;

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

public interface ServerInterface extends Remote ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

    public String ping(String fileName) throws

學習JavaFX Script,第二部分:使用RMI進行遠端通信

        RemoteException;

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

}

       和任何一個RMI程式一樣,ServerInterface必須符合下述要求:

       1、必須繼承Remote接口。

       2、為了用戶端可以加載一個實作了Remote接口的遠端對象,必須聲明為public。

       3、接口中的每一個方法(本例中隻包含了一個方法)必須抛出java.rmi.RemoteException。

       接下來的步驟是建立一個實作了ServerInterface的類。一個示例實作如代碼示例2所示。注意,除了實作ServerInterface外,ServerImpl類還要繼承UnicasRemoteObject。這說明ServerImpl類是用來建立一個單一的、不可複制的遠端對象,它使用RMI預設的TCP傳輸進行通信。這可能是無論任何時候使用RMI時需要做的所有事情。

        示例代碼2

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

import java.io.*;

學習JavaFX Script,第二部分:使用RMI進行遠端通信

import java.rmi.*;

學習JavaFX Script,第二部分:使用RMI進行遠端通信

import java.rmi.server.UnicastRemoteObject;

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

public class ServerImpl extends UnicastRemoteObject

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

    implements ServerInterface ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

    private String name;

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

    public ServerImpl() throws RemoteException...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信

        super();

學習JavaFX Script,第二部分:使用RMI進行遠端通信

    }

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

    public String ping(String s)...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信

        return "Hello " + s;

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

        第三步是開發伺服器。這個類将成為伺服器程式的入口,因為它包含了main()方法。伺服器必須完成以下三個任務:

        1、建立RMI注冊處(RMI registry)。

        2、建立一個遠端的執行個體——本例中,是ServerImpl。

        3、注冊使用RMI注冊處建立的對象。

        一個示例實作如代碼示例3所示。

        代碼示例3

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

import java.rmi.registry.LocateRegistry;

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

public class ServerMain ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

    public static void main(String argv[]) ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

        try ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

            LocateRegistry.createRegistry(1099);

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

            ServerInterface s = new ServerImpl();

學習JavaFX Script,第二部分:使用RMI進行遠端通信

            Naming.rebind("//127.0.0.1/Server", s);

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

        } catch(Exception e) ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信

            System.out.println("Server: "+e.getMessage());

學習JavaFX Script,第二部分:使用RMI進行遠端通信

            e.printStackTrace();

學習JavaFX Script,第二部分:使用RMI進行遠端通信

        }

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

        Naming.rebind("//127.0.0.1/Server", s)語句假設RMI注冊處運作在預設的端口上,即代碼示例3中在LocateRegistry.createRegistry()語句定義的1099端口。可是,如果RMI注冊處運作在不同的端口上——例如,更改注冊位置建立語句為LocateRegistry.createRegistry(4500)——那麼你就要相應地将綁定語句過更改為:

學習JavaFX Script,第二部分:使用RMI進行遠端通信

Naming.rebind("//127.0.0.1:4500/Server", s)

        另外,特别需要注意的是,位址127.0.0.1是一個專用的localhost位址,它假定RMI注冊位置和伺服器運作在同一台機器上。如果它們不是運作在同一台機器上,隻需要簡單的更改rebind()方法中的位址,和RMI注冊處的IP位址相适應。

         接下來步驟是在JavaFXClient工程中完成的,它和傳統RMI程式不同:現在必須建立一個Java連接配接助手。這個連接配接助手遠端調用遠端接口——ServerInterface——中指定任何方法,然後把結果傳回到調用它的JavaFX Script。為了完成這個任務,連接配接助手首先需要從RMI注冊處獲得遠端對象的引用。一旦獲得了引用,就可以調用适當的方法。

        代碼示例4中給出了實作。注意,這隻是一個簡單的靜态方法,通過它JavaFX Script可以獲得遠端ServerInterfacde的實作對象的引用。

        代碼示例4

學習JavaFX Script,第二部分:使用RMI進行遠端通信

package client;

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

import server.ServerInterface;

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

public class ConnectionHelper ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

    public static ServerInterface getConnection()

學習JavaFX Script,第二部分:使用RMI進行遠端通信

        throws Exception

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

    ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信

        return (ServerInterface)

學習JavaFX Script,第二部分:使用RMI進行遠端通信

            Naming.lookup("rmi://127.0.0.1:1099/Server");

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

        再一次需要注意,這段代碼假定RMI注冊處和用戶端運作在同一台機器上。如果不是這樣,修改IP位址——如果需要,同時修改端口——使二者比對。

        然而,為了簡單期間,你可以隻完成其中的一個:

        1、複制ServerInterface的源檔案到JavaFXClient工程的client中。

        2、修改JavaFXClient工程的屬性,使其包含JavaRMIProject工程。

        無論使用哪種方式,都要在源碼頂部中增加适當的導入語句,如代碼示例4所示。

        最後,代碼示例5給出了尅用來建立JavaFX Script用戶端的代碼,該用戶端通過RMI和遠端伺服器通信。将代碼示例5中的代碼複制到MyClient.fx檔案中。

        代碼示例5

學習JavaFX Script,第二部分:使用RMI進行遠端通信

import java.lang.*;

學習JavaFX Script,第二部分:使用RMI進行遠端通信

import javafx.ui.*;

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

import client.ConnectionHelper;

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

class ButtonClickModel ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信

    attribute numClicks: Number;

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

var model = new ButtonClickModel();

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

var win = Frame ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信

    width: 200

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

    content: GridPanel ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

        border: EmptyBorder ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信

           top: 30

學習JavaFX Script,第二部分:使用RMI進行遠端通信

           left: 30

學習JavaFX Script,第二部分:使用RMI進行遠端通信

           bottom: 30

學習JavaFX Script,第二部分:使用RMI進行遠端通信

           right: 30

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

        rows: 3

學習JavaFX Script,第二部分:使用RMI進行遠端通信

        columns: 1

學習JavaFX Script,第二部分:使用RMI進行遠端通信

        vgap: 10

學習JavaFX Script,第二部分:使用RMI進行遠端通信

        cells:

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

          [  Button ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信

                 text: "Click to make RMI connection!"

學習JavaFX Script,第二部分:使用RMI進行遠端通信

                 mnemonic: I

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

                 action: operation() ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

                     try ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

                         var remoteServer:ServerInterface =

學習JavaFX Script,第二部分:使用RMI進行遠端通信

                             ConnectionHelper.getConnection();

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

                         var results = remoteServer.ping("Test");

學習JavaFX Script,第二部分:使用RMI進行遠端通信

                         System.out.println("response: {results}");

學習JavaFX Script,第二部分:使用RMI進行遠端通信

                         model.numClicks++;

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

                     } catch (e:Exception) ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信

                         System.out.println("exception: {e}");

學習JavaFX Script,第二部分:使用RMI進行遠端通信

                     }

學習JavaFX Script,第二部分:使用RMI進行遠端通信

                 }

學習JavaFX Script,第二部分:使用RMI進行遠端通信

             },

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

             Label ...{

學習JavaFX Script,第二部分:使用RMI進行遠端通信

                 text: bind "Number of RMI connections: {model.numClicks}"

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

             }

學習JavaFX Script,第二部分:使用RMI進行遠端通信

          ]

學習JavaFX Script,第二部分:使用RMI進行遠端通信
學習JavaFX Script,第二部分:使用RMI進行遠端通信

    visible: true

學習JavaFX Script,第二部分:使用RMI進行遠端通信

};

         現在,編譯和運作服務端工程。接着,運作用戶端工程。應該可以看到類似圖3所示的界面。點選“Click to make RMI connection”按鈕。一段時間後,檢查是否有響應資訊輸出到了NetBeans IDE底部的輸出控制台上。每連接配接成功一次,按鈕下面的計數器就會增加一。

              圖3  JavaFX用戶端調用遠端伺服器

          總結(Conclusion)

          本文簡單介紹了使用JavaFX Script和RMI進行用戶端--伺服器程式設計的方法。在本文中,JavaFX平台應用在整個用戶端中。本系列的第三部分将讨論使用JavaFX平台和Java API for XML Web Services(JAX-WS)處理用戶端--伺服器通信的方式。以後的文章中将使用已有的用戶端-伺服器Java代碼內建到JavaFX Script平台中。

         更多資訊參考(For More Information)

<a href="http://java.sun.com/developer/technicalArticles/scripting/javafxpart1/">Learning JavaFX Script, Part 1: An Introduction to JavaFX Script for Java Programmers.</a>