love fish大鵬一曰同風(fēng)起,扶搖直上九萬里

          常用鏈接

          統(tǒng)計

          積分與排名

          friends

          link

          最新評論

          使用 Google Web Toolkit 開發(fā) Ajax(轉(zhuǎn))

          Ajax技術(shù)是當(dāng)前開發(fā)web應(yīng)用的非常熱門的技術(shù),也是Web 2.0的一個重要的組成部分。然而如果用傳統(tǒng)的方式Javascript進(jìn)行Ajax開發(fā)的話,就會使得應(yīng)用程序非常難以進(jìn)行調(diào)試,從而降低了生產(chǎn)效率。Google最近推出的GWT有望為我們解決這個難題,GWT是一個開發(fā)Ajax應(yīng)用的框架,它使程序員用Java同時開發(fā)客戶端和服務(wù)器端的代碼。GWT的編譯器會把用于開發(fā)客戶端的Java代碼轉(zhuǎn)化成Javascript和Html,而程序員不用關(guān)心這一轉(zhuǎn)換過程。這樣程序員就可以在自己喜歡的Java IDE里面開發(fā)自己的Ajax應(yīng)用程序。

          本文主要從以下幾個方面進(jìn)行介紹:

          1、 GWT特性簡介

          2、 用GWT進(jìn)行UI開發(fā)

          3、 用Javascript開發(fā)Ajax應(yīng)用簡介

          4、 用GWT進(jìn)行Ajax開發(fā)

          GWT特性簡介

          1.動態(tài),可重用的UI組件

          GWT提供的組件庫使用戶可以很容易的開發(fā)出漂亮的UI, 每個組件對應(yīng)于GWT的一個類。在本文的第二部分會比較詳細(xì)的介紹GWT對UI的支持。

          2.簡單的RPC調(diào)用

          使用GWT,可以方便的實現(xiàn)客戶端和服務(wù)器端的通信,特別是使得異步通信變的非常簡單。在本文的后面部分將對利用GWT進(jìn)行RPC調(diào)用進(jìn)行詳細(xì)介紹。

          3.更加方便的調(diào)試

          由于在開發(fā)階段不需要生成HTML截面,用戶開發(fā)的代碼實際上是在JVM上運(yùn)行的,這樣用戶就可以用傳統(tǒng)的調(diào)試Java代碼的方法對程序進(jìn)行調(diào)試,從而加快了調(diào)試的速度,減少了軟件開發(fā)的時間。

          4.瀏覽器兼容性

          在大多數(shù)情況下,用GWT開發(fā)出來的程序會支持IE、Firefox、Mozilla、Safari和Opera,用戶在開發(fā)的時候不必?fù)?dān)心瀏覽器的兼容性問題。而瀏覽器的兼容性問題也是用直接用Javascript進(jìn)行Ajax應(yīng)用開發(fā)所面臨的一個另程序員棘手問題。

          5.可擴(kuò)展性

          如果你覺得GWT提供的API不能滿足需求,你可以利用JSNI將Javascript語句直接嵌入至Java代碼中。?

          用GWT進(jìn)行UI開發(fā)

          在本文的這一部分,我們將探討一下GWT對UI開發(fā)的支持。在GWT中,包含我們進(jìn)行Web開發(fā)所需要的大部分組件,比如按紐(Button),文本框(Text box)等。圖一顯示了部分GWT所支持的UI組件。從圖片的顯示效果來看,利用GWT可以做出非常漂亮的UI。


          圖一:GWT支持的部分UI組件
          圖一:GWT支持的部分UI組件

          值得一提的是,在每個UI組件是必須放在一個稱之為面板(Panel)的控件里面。而面板具有不同的風(fēng)格,這也決定了UI的風(fēng)格。圖二顯示了GWT所支持的部分面板。


          圖二:GWT支持的部分面板
          圖二:GWT支持的部分面板

          在看過這些組件之后,我們接下來用一個實驗來講述怎樣把UI組件添加到頁面上。這個實驗的最終結(jié)果是一個登錄框界面。

          在開始我們的實驗之前,我們需要準(zhǔn)備一下GWT環(huán)境,首先要到Google的網(wǎng)站上去下載一個Windows版本的GWT,目前的版本號是1.0.21。然后要在機(jī)器上配置好JDK環(huán)境,具體的配置方法網(wǎng)絡(luò)上有大量文檔,這里就不再詳細(xì)介紹。由于我們這個實驗是在Eclipse開發(fā)環(huán)境下進(jìn)行的,所以你還需要一個Eclipse的環(huán)境,可以到Eclipse的官方網(wǎng)站下載Eclipse的開發(fā)環(huán)境。接下來我們詳細(xì)介紹試驗過程。

          1. 創(chuàng)建Eclipse工程

          我們可以利用GWT自帶的一個批處理文件projectCreator.cmd來創(chuàng)建Eclipse的工程。如圖三所示,我們創(chuàng)建了一個名字為myProject的工程,存放在當(dāng)前目錄的myProject子目錄下面,關(guān)于批處理文件projectCreator.cmd的詳細(xì)用法,請參見Google關(guān)于GWT的幫助文檔


          圖三:用GWT創(chuàng)建Eclipse工程
          圖三:用GWT創(chuàng)建Eclipse工程

          2. 創(chuàng)建GWT應(yīng)用程序

          在創(chuàng)建完Eclipse工程myProject之后,我們利用GWT自帶的另外一個批處理文件applicationCreator.cmd來創(chuàng)建一個GWT應(yīng)用程序。圖四顯示了創(chuàng)建一個GWT應(yīng)用的過程。大家注意到這個批處理文件接受一個名為 -eclipse 的參數(shù),這個參數(shù)正是指定了一個Eclipse的工程,我們的例子中指定為我們剛創(chuàng)建好的Eclipse工程myProject。


          圖四:創(chuàng)建GWT應(yīng)用程序
          圖四:創(chuàng)建GWT應(yīng)用程序

          3. 導(dǎo)入Eclipse工程

          在創(chuàng)建完Eclipse工程和GWT應(yīng)用程序框架后,我們接著將Eclipse工程導(dǎo)入到Eclipse開發(fā)環(huán)境當(dāng)中以進(jìn)行進(jìn)一步的開發(fā),具體的導(dǎo)入過程不再詳細(xì)介紹。導(dǎo)入后的工程結(jié)構(gòu)如圖五所示。


          圖五:導(dǎo)入Eclipse工程
          圖五:導(dǎo)入Eclipse工程

          6.添加UI組件

          在導(dǎo)入工程后,我們會發(fā)現(xiàn)工程里面有一個名字為DemoClient的Java文件。這個文件是在運(yùn)行applicationCreator.cmd批處理文件時創(chuàng)建的,我們現(xiàn)在需要做的工作就是在這個Java文件上加入自己需要的UI組件。我們在這個文件中加入了五個組件,分別是:兩個Label,一個Button,一個TextBox和一個PasswordTextBox。代碼列表Listing 1中列出了本程序的所有代碼。


          Listing 1:Sample GWT Application

          1    package com.sample.myProject.client;
          
          2    import com.google.gwt.core.client.EntryPoint;
          3    import com.google.gwt.user.client.ui.Button;
          4    import com.google.gwt.user.client.ui.HorizontalPanel;
          5    import com.google.gwt.user.client.ui.Label;
          6    import com.google.gwt.user.client.ui.PasswordTextBox;
          7    import com.google.gwt.user.client.ui.RootPanel;
          8    import com.google.gwt.user.client.ui.TextBox;
          
          /**
           * This class is used to demostrate how to add widget onto the Web page
           */
          9    public class DemoClient implements EntryPoint {
            /**
             * This is the entry point method, when the module is load, this method
             * will be automatically invoked.
             */
          10	  public void onModuleLoad() {
          11		    Label labelName = new Label();
          12		    Label labelPassword = new Label();		    
          13		    TextBox tbName = new TextBox();
          14	PasswordTextBox tbPassword = new PasswordTextBox();
          15	Button button = new Button();
          16		    
          17		    labelName.setText("Name:        ");
          18		    labelPassword.setText("Password: ");
          19		    button.setText("submit");
          20		    
          21		    HorizontalPanel hPanel = new HorizontalPanel();
          22		    HorizontalPanel hPanel2 = new HorizontalPanel();
          23		    
          24		    hPanel.add(labelName);
          25		    hPanel.add(tbName);
          26		    hPanel2.add(labelPassword);
          27		    hPanel2.add(tbPassword);
          		    
          28		    RootPanel.get().add(hPanel);
          29		    RootPanel.get().add(hPanel2);
          30		    RootPanel.get().add(button);
          31		  }
          32   }
          

          接下來我們分析一下這些程序代碼,注意到類DemoClient繼承自EntryPoint,所有需要最終被翻譯成HTML頁面的類都必須繼承自EntryPoint,并且需要重寫onModuleLoad方法,這個方法會在模塊被裝載的時候自動調(diào)用。因此我們也就需要把我們的添加組件的代碼放到這個函數(shù)里面。

          程序的11至15行分別創(chuàng)建了5個組件的實例。分別是兩個Label,一個Button,一個TextBox和一個PasswordTextBox。然后程序的17到19行分別設(shè)置了兩個Label組件以及一個Button組件的顯示內(nèi)容。程序的21行和22行穿件兩個Panel對象,這兩個Panel對象的類型都是水平Panel對象。也就是說放在這種Panel里面的組件是被水平排列的。程序的24行到27行分別向這兩個Panel對象中加入TextBox組件和Label組件。在程序的最后,將剛才創(chuàng)建好的兩個Panel對象以及一個Button對象加到最外層的Panel當(dāng)中。

          7.編譯應(yīng)用程序

          在代碼開發(fā)完成后,我們可以雙擊工程里面的DemoClient-compile.cmd批處理文件來將我們開發(fā)出來Java文件編譯成Javascript和HTML。編譯后的文件將存放在工程的根目錄下面的www子目錄中。

          8.運(yùn)行程序

          編譯好程序后,我們會發(fā)現(xiàn)生成了一個名字為DemoClient.html的HTML文件,雙擊這個文件,程序的運(yùn)行結(jié)果如圖六所示:


          圖六:程序運(yùn)行結(jié)果
          圖六:程序運(yùn)行結(jié)果

          在這一部分,我們主要討論了如何將UI組件添加到Web頁面中,而這些組件如何與遠(yuǎn)程服務(wù)器進(jìn)行異步的交互將在下面的章節(jié)中進(jìn)行討論。

          用Javascript開發(fā)Ajax應(yīng)用

          為了使用戶能更清楚地理解用GWT開發(fā)Ajax應(yīng)用與用傳統(tǒng)的Javascript開發(fā)Ajax應(yīng)用的不同,文章的這一部分將簡要介紹如何利用Javascript對象進(jìn)行Ajax應(yīng)用的開發(fā)。

          大家都知道Ajax技術(shù)中的一個核心對象是XMLHttpRequest對象,這個對象支持異步請求,所謂異步請求既是當(dāng)客戶端發(fā)送一個請求到服務(wù)器的時候,客戶端不必一直等待服務(wù)器的響應(yīng)。這樣就不會造成整個頁面的刷新,給用戶帶來更好的體驗。而當(dāng)服務(wù)器端響應(yīng)返回時,客戶端利用一個Javascript函數(shù)對返回值進(jìn)行處理,以更新頁面上的部分元素的值。

          由于在IE和其他瀏覽器上聲稱XMLHttpRequest對象的方法不一樣,所以我們用Javascript創(chuàng)建XMLHttpRequest對象的時候必須區(qū)分不同的瀏覽器。創(chuàng)建一個XMLHttpRequest對象的方法如清單2 中的代碼所示。


          清單2:創(chuàng)建XMLHttpRequest對象

          1    function createObject(){
          2     try {
          3		  xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
          4	  } catch (e1) {
          5		  try {
          6		    xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
          7		  } catch (e2) {
          8		    xmlHttpRequest = false;
          9		  }
          10	  }
          11  if (!xmlHttpRequest) {
          12		 xmlHttpRequest = new XMLHttpRequest();
          13	  }
          14	  return xmlHttpRequest;      
          16  }
          

          在創(chuàng)建好XMLHttpRequest對象之后,來看一下如何與server端進(jìn)行異步的交互。清單3中列出了與服務(wù)器段進(jìn)行交互的代碼


          清單3:與服務(wù)器端進(jìn)行交互

          1    function ajaxSample() {
          2        var xmlHttpRequest = createObject();
          3        var url = "/sampleServlet?userName=Jason";
          4        xmlHttpRequest.open("GET", url, true);
          5        xmlHttpRequest.onreadystatechange = updatePage;
          6        xmlHttpRequest.send(null);
          7    }
          

          這段代碼演示了如何與服務(wù)器端進(jìn)行交互的過程。程序的第2行首先獲得一個XMLHttpRequest對象,程序的第三行指定了服務(wù)器端響應(yīng)客戶端的請求的地址。程序的第4行利用XMLHttpRequest對象打開一個連接,第一個參數(shù)指定用GET方法傳遞參數(shù),第二個參數(shù)指定了接受請求的URL,在我們的例子中是一個Servlet,最后一個參數(shù)設(shè)置成true意味著將要發(fā)出的請求是一個異步的請求。程序的第5行指定了回調(diào)函數(shù),也就是當(dāng)服務(wù)器端返回結(jié)果后執(zhí)行哪個Javascript函數(shù)。

          這一部分對如何利用Javascript進(jìn)行Ajax開發(fā)作了一個簡要的介紹,下面我們將詳細(xì)介紹如何利用GWT進(jìn)行Ajax應(yīng)用的開發(fā)。

          用GWT進(jìn)行Ajax開發(fā)

          在文章的第二部分我們已經(jīng)掌握了如何利用GWT創(chuàng)建一個工程并在工程里添加一個GWT應(yīng)用程序,同樣我們這一部分也需要創(chuàng)建一個GWT的工程,并添加一個GWT應(yīng)用程序,由于默認(rèn)創(chuàng)建的GWT程序不含有Server端的示例代碼,我們必須手工加進(jìn)去。我們創(chuàng)建好的工程GWTSample如圖七所示。我們將要介紹的實例主要功能是采用異步通信的方式從服務(wù)器端取出一個字符串顯示在HTML頁面上。這個例子雖然簡單,但卻包含了如何利用GWT進(jìn)行Ajax開發(fā)的主要流程。


          圖七:GWTSample工程結(jié)構(gòu)
          圖七:GWTSample工程結(jié)構(gòu)

          大家注意到我們這個工程里面有個com.sample.myProject.server包,這個包里面包含有運(yùn)行在服務(wù)器端的代碼。我們從客戶端發(fā)送的請求也是發(fā)送到這個包里面的一個Servlet上去的。

          為了進(jìn)行異步調(diào)用,在Client端必須定義一個繼承自接口RemoteService的接口,在我們的這個例子中,我們定義了接口SampleService,SampleService的代碼如清單4所示。


          1    package com.sample.myProject.client;
          
          2    import com.google.gwt.user.client.rpc.RemoteService;
          
          3    public interface SampleService extends RemoteService{
          4    //The implementation of this method is used to return a string
          5    String getString();
          6    }
          

          大家注意到這個接口繼承自RemoteService,并且聲明了一個方法getString();,這個方法會在服務(wù)器端的代碼中實現(xiàn)。當(dāng)然,大家可能現(xiàn)在已經(jīng)意識到,這里聲明的方法就是我們采用異步調(diào)用方式所能夠調(diào)用的方法。

          在聲明完這個接口之后,我們還必須聲明另外一個異步調(diào)用接口,在我們的例子中是接口SampleServiceAsync,這個接口里聲明的方法名稱必須與SampleService里面的相同,但是多個一個類型為AsyncCallback的參數(shù),接口SampleServiceAsync的代碼清單如清單5所示:


          清單5:SampleServiceAsync代碼清單

          1    package com.sample.myProject.client;
          
          2    import com.google.gwt.user.client.rpc.AsyncCallback;
          
          3    public interface SampleServiceAsync {
          	
          4    void getString(AsyncCallback callback);
          5	}
          

          在客戶端定義完接口之后,我們必須在服務(wù)器端實現(xiàn)這個接口,在我們的例子中,類SampleServiceImpl實現(xiàn)了接口SampleService,同時你也會注意到SampleServiceImpl也繼承了類RemoteServiceServlet,而RemoteServiceServlet是HttpServlet的一個子類,這樣我們的客戶端的請求就可以提交到Servlet SampleServiceImpl上面。類SampleServiceImpl的代碼清單如清單6所示:


          清單6:SampleServiceImpl代碼清單

          1    package com.sample.myProject.server;
          
          2    import com.google.gwt.user.server.rpc.RemoteServiceServlet;
          3    import com.sample.myProject.client.SampleService;
          
          4	public class SampleServiceImpl extends RemoteServiceServlet implements 
          5	 SampleService {
          6          public String getString() {
          7         return "This string is from server";
          8          }
          9	}
          

          最后我們來看一下類DemoClient,這個類和我們在第二部分創(chuàng)建的工程myProject中的類DemoClient是同一個類型的。只不過在我們這個工程中我們使用它來進(jìn)行向server端的異步調(diào)用。清單7列出了類DemoClient的代碼。


          清單7:DemoClient代碼清單

          1    package com.sample.myProject.client;
          
          2    import com.google.gwt.core.client.EntryPoint;
          3    import com.google.gwt.core.client.GWT;
          4    import com.google.gwt.user.client.rpc.AsyncCallback;
          5    import com.google.gwt.user.client.rpc.ServiceDefTarget;
          6    import com.google.gwt.user.client.ui.Button;
          7    import com.google.gwt.user.client.ui.ClickListener;
          8    import com.google.gwt.user.client.ui.Label;
          9    import com.google.gwt.user.client.ui.RootPanel;
          10   import com.google.gwt.user.client.ui.Widget;
          
          /**
           * This class is used to demostrate hwo to 
           * interact with the server client in asynchronized
           * way
           */
          11   public class DemoClient implements EntryPoint {
          
          12       public void onModuleLoad() {
          13	final SampleServiceAsync sampleService = (SampleServiceAsync) 
          14	 GWT.create(SampleService.class);
          15        ServiceDefTarget target = (ServiceDefTarget)sampleService;
          16        String staticResponseURL = GWT.getModuleBaseURL();
          17        staticResponseURL += "/getStringService";
          18        target.setServiceEntryPoint(staticResponseURL);
          19        
          20        final Label label = new Label();
          21        final Button button = new Button("Get String");
                  
          22        button.addClickListener(new ClickListener() {
          23            public void onClick(Widget sender) {
          24                sampleService.getString(new AsyncCallback() {
          25                    public void onSuccess(Object result) {
          26                        label.setText((String) result);
          27                    }
          28                    public void onFailure(Throwable caught) {
          29                        label.setText(caught.getMessage());
          30                    }
          31                });
          32            }
          33        });
          
          34        RootPanel.get("1").add(button);
          35        RootPanel.get("2").add(label);
          36    }
          37}
          

          代碼的第13行得到了一個實現(xiàn)了接口SampleServiceAsync的類的實例。第15行創(chuàng)建了一個ServiceDefTarget對象的一個實例,通過這個對象可以設(shè)置請求的目的地。程序的第18行設(shè)置了請求的目的地的URL,在我們的例子中是"/getStringService",這個URL會在web.xml文件中被mapping到servlet SampleServiceImpl上。程序的22行到33行為我們添加的button設(shè)置了單擊響應(yīng)事件。在單擊響應(yīng)事件中調(diào)用sampleService的getString(AsyncCallback callback);方法。這個方法是用來進(jìn)行異步的遠(yuǎn)程過程調(diào)用的(RPC).并且在實現(xiàn)接口AsyncCallback的代碼中指定了回調(diào)函數(shù),當(dāng)遠(yuǎn)程過程調(diào)用成功后就執(zhí)行onSuccess(Object result)函數(shù),其中result中存放有從服務(wù)器端返回的結(jié)果.。在遠(yuǎn)程工程調(diào)用失敗后就執(zhí)行onFailure(Throwable caught)函數(shù)。程序的最后把Button組件和Label組件加到panel中。

          現(xiàn)在我們已經(jīng)完成了程序的開發(fā),圖八顯示了我們程序的運(yùn)行結(jié)果,在點擊Button后,右邊回打出一句話來,重要的是這句話是以異步的方式從服務(wù)器端取得的,不需要進(jìn)行頁面的刷新,怎么樣,現(xiàn)在是不是也想用GWT進(jìn)行Ajax應(yīng)用開發(fā)了呢?


          圖八:RPC調(diào)用示例
          圖八:RPC調(diào)用示例

          總結(jié)

          本文主要對用 GWT 進(jìn)行 Ajax 開發(fā)進(jìn)行了比較詳細(xì)的介紹,并通過與傳統(tǒng)的Ajax開發(fā)方式進(jìn)行比較,使讀者能更清楚地理解它們之間的區(qū)別,最后我們可以看出用GWT進(jìn)行Ajax開發(fā)可以使得程序員免受調(diào)試Javascript之苦,并且GWT自動處理了瀏覽器之間的兼容性問題,這些都會使得開發(fā)更加容易,快捷。因此,用GWT進(jìn)行Ajax開發(fā)是一種比較好的方式。希望本文能為讀者學(xué)習(xí)GWT進(jìn)行Ajax的開發(fā)有所幫助。

          下載

          GWTSample_Project.rar 8KB HTTP


          posted on 2006-07-25 13:26 liaojiyong 閱讀(408) 評論(0)  編輯  收藏 所屬分類: Ajax

          主站蜘蛛池模板: 龙陵县| 牙克石市| 鄢陵县| 成都市| 广州市| 莱州市| 会理县| 亳州市| 长治县| 明溪县| 玛沁县| 莫力| 景德镇市| 祁阳县| 远安县| 增城市| 赤壁市| 杭州市| 商都县| 慈溪市| 嵊泗县| 新兴县| 通州市| 务川| 西城区| 元谋县| 饶平县| 天津市| 仲巴县| 十堰市| 沙湾县| 万山特区| 吉林省| 射洪县| 枣庄市| 龙陵县| 财经| 漳州市| 东海县| 永泰县| 通山县|