天天看點

GWT 學習總結

最近上司讓研究GWT,學習這個AJAX架構,看看對我們的系統能否內建進去,花了1周多時間研究啊。照葫蘆畫瓢,做了一個Demo,對這個架構也有了一個初步的認識, 感覺就是一個Web的 SWT。

GWT 學習筆記

一、使用者界面(User Interface)

在開發GWT應用程式時要注意一件事,它的開發非常像Swing,SWT,甚至是VB。你建立按鈕、清單、表單,經事件監聽器與之互動。你進行布局,試着讓它們在一定的螢幕分辨率和螢幕尺寸下看起來更好看。主要的不同之處在于GWT應用是顯示在Web浏覽器上,它涉及到HTML頁面。

傳統的Web應用程式是以一系列的HTML頁面為結構,并以之導航的。

1、與HTML的聯系

每一個GWT應用程式裡面都存在一個HTML頁面,它可以是一個靜态的頁面,或者是伺服器端的頁面如JSP,Struts,Ruby on Rails等。

實際上,MyApp.html存在于public目錄,意味着它将被一字不差的複制到最終的伺服器端的部署區域,如果頁面還連結着圖檔,樣式表等,它們也都會複制到同樣的目錄下。

在HTML頁面代碼的頂部需要meta标簽來聯系GWT元件。

如:<meta name='gwt:module' content='com.xyz.MyApp'>

一個GWT元件是一個用戶端代碼和資源的集合。名為com.mycompany.MyApp的元件被定義到元件檔案src/com/mycompany/MyApp.gwt.xml中。

-----------------------------------------------

<module>

<!-- Inherit the core Web Toolkit stuff. -->

<inherits name='com.google.gwt.user.User'/>

<!-- Specify the app entry point class. -->

<entry-point class='com.xyz.client.MyApp'/>

</module>

-----------------------------------------------

在邏輯上,當HTML頁面載入後,GWT檢視meta标簽,讀入xml檔案并得到類名,在入口點類中開始調用代碼。

2、入口點(Entry Point)

入口點類(MyApp)擴充了入口點接口并提供了一個方法onModuleLoad()。這個方法在構造GWT應用程式使用者界面中起作用。

MyProject/src/com/xyz/client/MyApp.java

-----------------------------------------------

public void onModuleLoad(){

final Button button=new Button("Click me");

final Label label=new Label();

//...

-----------------------------------------------

上面的腳手架代碼建立了兩個GWT使用者界面元素,一個按鈕和一個标簽。

如果要追溯和浏覽HTML檔案,其代碼底部有兩個占位符用于動态内容:

MyProject/src/com/xyz/public/MyApp.html

-----------------------------------------------

<table align=center>

<tr>

<td id="slot1"></td>

<td id="slot2"></td>

</tr>

</table>

-----------------------------------------------

Java代碼将通過“id=”來引用并填充你建立的按鈕和标簽。

MyProject/src/com/xyz/client/MyApp.java

-----------------------------------------------

RootPanel.get("slot1").add(button);

RootPanel.get("slot2").add(label);

-----------------------------------------------

上面的表定義了怎樣使用小部件在螢幕上布局。

還有一個更好的布局方式是使用面闆(Panel)。GWT面闆也是一個小部件,它能容納一個或多個小部件并以特殊的方式管理它們。

例如:你可以建立一個水準面闆(Horizontal Panel),在其上加入按鈕和标簽,再把該面闆加入到RootPanel的頁面。即:

RootPanel.get().add(hPanel);

3、事件(Event)

繼續看剛才的例子,讓按鈕做一些事:

MyProject/src/com/xyz/client/MyApp.java

-----------------------------------------------

button.addClickListener(new ClickListener(){

public void onClick(Widget sender){

...

-----------------------------------------------

4、小部件(Widget)

(1)檔案上傳 FileUpload

設定輸入element的名字并使用setName()方法送出到伺服器。

(2)伸縮表和網格 FlexTable and Grid

表可以包含文本、HTML和其它任意小部件。網格總是相同的,有固定的尺寸。

使用setText(),setHTML(),setWidget()方法來加入單元項,使用getCellFormatter()來定制單元的外觀。單元可以跨越多行或多列。

(3)Frame and NamedFrame

此部件包裹在HTML的<iframe>元素中,包含于任意Web站點。

使用setUrl()方法來設定web頁面位址。

其CSS風格:.gwt-Frame{}

(4)HTML

其CSS風格:.gwt-HTML{}

(5)Image

在給定的URL顯示圖檔的小部件。

使用setUrl()方法來設定圖檔位址。使用addLoadListener()方法來檢測圖檔是否載入或是否有錯。

其CSS風格:.gwt-Image{}

(6)Hyperlink

其CSS風格:.gwt-Hyperlink{}

(7)Label

其CSS風格:.gwt-Label{}

(8)ListBox

其CSS風格:.gwt-ListBox{}

(9)MenuBar and MenuItem

使用addItem()來加入菜單欄。

其CSS風格:

.gwt-MenuBar{the menu bar itself}

.gwt-MenuItem{menu items}

.gwt-MenuItem-selected{selected menu items}

.gwt-Frame{}

(10)PasswordTextBox

其CSS風格:.gwt-PasswordTextBox{}

(11)TabBar

常用于Tab面闆的一部分。調用addTab()方法來加入TarBar,調用addTabListener()來檢測聚焦前(onBeforeTabSelected())和聚集後(onTabSelected())tab被選擇的情況。

其CSS風格:

.gwt-TarBar{the tab bar itself}

.gwt-TarBarFirst{the left side spacer of the bar}

.gwt-TabBarRest{the right side spacer of the bar}

.gwt-TabBarItem{tabs}

.gwt-TabBarItem-selected{additional style for selected tabs}

(12)TextArea

文本域允許顯示鍵入的多行文本。使用setCharacterWidth()和setVisibleLines()方法來設定文本域的尺寸。

調用getCursorPos(),getSelectionLength(),getSelectedText()來檢測目前所選擇的文本。

調用addKeyBoardListener()方法來監測按鍵情況。

其CSS風格:.gwt-TextArea{}

(13)TextBox

文本框顯示鍵入的單行文本。

設定文本框的尺寸用setVisibleLength()方法。

調用getCursorPos(),getSelectionLength(),getSelectedText()來檢測目前所選擇的文本。

調用addKeyBoardListener()方法來監測按鍵情況。

(14)Tree and TreeItem

調用addItem()方法增加樹子項。

其CSS風格:

.gwt-Tree{the tree itself}

.gwt-TreeItem{a tree item}

.gwt-TreeItem-selected{a selected tree item}

5、面闆(Panel)

面闆是一個包含多個小部件的部件。面闆也可以包含其它面闆。可以使用它在網格下、層面下(deck)、行、列下布局小部件。

(1)AbsolutePanel

允許面闆重疊。

(2)DeckPanel

所有的小部件在一個“deck”中,一次隻能顯示一個小部件。

用add()方法加入小部件,用showWidget()顯示某個小部件。

(3)DockPanel

面闆的中央部分是保留部分,四周東西南北均可添加部件。

(4)FlowPanel

使用預設的HTML布局。

(5)FocusPanel

(6)FormPanel

面闆的内容對應HTML的<form>元素。

FormPanel隻包含如下元素:TextBox,PasswordTextBox,RadioButton,CheckBox,TextArea,ListBox,FileUpload。

使用setName()方法把各元素名和表單域聯系在一起,傳遞到伺服器。

使用setAction()方法設定URL用于送出表單。submit()實際送出表單。

調用addFormHandler()檢測表單是否已送出。

(7)HorizontalPanel

(8)HTMLPanel

(9)PopupPanel

popup面闆可以彈出其它小部件。

(10)ScrollPanel

面闆的内容可卷。使用構造器或者setWidget()函數定義包裹的部件。

(11)StackPanel

垂直的方式顯示,類似于子菜單。

(12)TabPanel

(13)VerticalPanel

功能介紹(Web控件)

Web控件是GWT表示層的核心,通過使用GWT提供的Web控件可以建立豐富的用戶端畫面。

GWT的web元件主要分為兩類:輸入控件和Layout控件。

輸入控件主要是指向伺服器送出資料,處理操作,顯示伺服器資料的空間,主要包括:

Button,RadionButton,PushButton,ToggleButton,CheckBox,TextBox,PasswordBox

TextArea, HyperLink,ListBox,MenuBar,Tree,Table, TabBar,DialogBox, PopupPanel

RichTextArea, DisclosurePanel, SuggestBox

Layout 空間主要用來有規律地放置輸入控件,主要包括:

Stackpanel,HorizontalPanel,VerticalPanel, FlowPanel, VerticalSplitPanel, HorizontalSplitPanel,

DockPanel, TabPanel,

事件模型(Event & Listener)

如何處理頁面的事件呢,例如點選按鈕,Textbox失去焦點等?

如下的代碼建立了一個按鈕,按鈕的名字是“Click Me”,當你點選這個按鈕的時候處罰一個Click事件,Click事件觸發onClick(Widget sender)方法。

sender表示觸發onClick方法的元件,這裡隻是簡單的在頁面上顯示Hello World資訊(相當于#的alert方法)。

常見的Listener如下:

ChangeListener

ClickListener

FocusListener

KeyboardListener

MouseListener

MouseWheelListener

PopupListener

ScrollListener

TableListener

TreeListener

功能介紹(遠過程調用RPC)

體系結構

GWT應用中頁面一旦加載,就再也不會向伺服器請求HTML内容,所有的畫面遷移,轉換都在用戶端進行,但是資料還是會向伺服器送出,或者從伺服器擷取。

伺服器上負責處理資料的對象在GWT中叫做Service,每個Service有三個類組成:服務方法定義接口(Service),異步調用接口(ServiceAsync)和伺服器方法實作類ServiceImpl。

以Login為例子說明:

遠端調用

獲得伺服器方法的調用接口(skeleton)。

設定服務位置。

遠端調用伺服器上的方法,注意這裡是異步調用,在和調用之前代碼可能先被調用了。

調用出錯,或者調用方法抛出異常的時候調用的方法。

調用成功傳回時候調用的方法。

參數和傳回值系列化類型

這裡的參數指的是Service方法調用的參數和傳回值。

由于GWT的用戶端代碼都是#,而伺服器代碼都是使用Java編寫的,這就涉及到#調用Java方法的時候

如何傳遞參數,如何取得傳回值的問題。

可序列化的類型包括:

(1) 原始類型,例如:char, byte, short, int, long, boolean, float, double;

(2) String,java.util.Date,或者原始類型的包裝類型,例如: Character, Byte, Short, Integer, Long, Boolean, Float, or Double;

(3) 可序列化類型數組(包含(4)和(5)定義的類型)

(4) 使用者定義的可序列化類型

(5) 該類型至少有一個可序列化的子類型

針對上述(4)中說明的,什麼是使用者自定義的可序列化類型呢?必須滿足以下亮點:

第一,必須直接或者間接(例如,父類型實作了這個接口)的實作了IsSerializable接口

第二,所有非transient類型都是可序列化的(final類型的屬性在GWT中被視為transient類型)

是否支援容器類型呢?那麼又如何聲明呢?

支援容器類型,GWT可以使用Type 參數來表示容器類型内部的元素的類型,例如:

注意GWT暫時不支援使用 JDK 5.0 的模闆容器

//使用者自定義序列化類型

public class MyClass implements IsSerializable {

public Set setOfStrings;

public Map mapOfStringToString;

}

// 伺服器方法實作類

public interface MyService extends RemoteService {

List reverseListAndConvertToStrings(List c);

}