一 GWT是什麼?
1 簡介
“The heart of GWT is a compiler that converts Java source into JavaScript, transforming your working Java application into an equivalent JavaScript application.”
GWT是一個javascript或者說ajax的開發工具。但使用java作為開發語言。使用者編寫的java code由GWT Compiler編譯成js腳本。
這裡的java code是受限的java語言。它與java語言标準基本一緻(稍許差別),但支援的java類庫僅有java.lang, java.util。具體的差別參見文檔:GWT文檔的Develop Guide>Fundamentals >GWT Compiler。
2 開發流程
Code In java, test , debug (hosted mode)
Compile into javascript
Run (web mode)
3 開發工具
GWT(projectCreator.cmd, applicationCreator.cmd, junitCreator.cmd, lib)
ant
eclipse
4 開發流程
使用projectCreator.cmd, applicationCreator.cmd建立一個工程,程式
project-Creator
Src
.project
.classpath
projectName.ant.xml
applicationCreator.cmd(建立用戶端類):
appName-compile.cmd
appName-shell.cmd
appName.launch
src/com/comName/projectName/client/app.java
src/com/comName/projectName/public/app.html
src/com/comName/projectName/app.gwt.xml
二 專題
1 構造複雜頁面(參見:Develop Guide>Buiding User Interface)
由GWT生成的工程,是為了開發采用了AJAX技術的web應用程式。他工作起來更像一個運作在浏覽器中的應用程式。網頁的界面一部份是html文檔中的靜态頁面,另一部份是由js腳本生成的。生成界面的腳本由GWT編譯器編譯java程式得到。
在開發時,對于界面,我們要做的工作就是:編輯靜态頁面(位于src/com/comName/projectName/public中),以及開發java源程式以生成js腳本(位于src/com/comName/projectName/client中)。
在GWT中,僅支援java.lang, java.util類庫, 不支援java.awt, javax.swing這些java界面類庫。在GWT工程的java程式中,界面的實作是通過使用GWT提供的界面類庫,(主要的類有:com.google.gwt.user.client.ui.Widget,com.google.gwt.user.client.ui.Panel)來實作的。
下面我們通過一個例子來看看腳本生成的界面。
在GWT開發過程中,一個application最基本的構成由一個靜态網頁和一個java源程式。Java源程式必須包含一個public void onModuleLoad()函數,這個函數是繼承自com.google.gwt.core.client.EntryPoint一個函數(但在給出的sample中有一個類沒有實作該接口);在這個函數中通過操縱com.google.gwt.user.client.ui.RootPanel來向網頁中增加界面内容。以下是一個最簡單的java源程式的構成:
package com.google.gwt.sample.hello.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
public class Hello implements EntryPoint {
public void onModuleLoad() {
Button b = new Button("Click me", new ClickListener() {
public void onClick(Widget sender) {
Window.alert("Hello, AJAX ");
}
});
RootPanel.get().add(b);
}
}
RootPanle.get()函數仍然傳回一個RootPanle對象,參數是一個字元串或者為空。這個參數的意義是:它對應于該application中靜态頁面中一個元素的id屬性。傳回的是給id對應元素關聯的RootPanle對象,也就是該元素對應的顯示區域。
Panel的概念和javax.swing中Panel的概念類似,Widget和javax.swing中的控件的概念類似。
一些基本的控件在GWT文檔的Develop Guide>Buiding User Interface>Widgets Gallery中有一個展示。
由js腳本生成并添加到頁面中的控件在靜态頁面的源檔案中沒有任何html代碼資訊。
2 事務處理及Layout
與java.awt, javax.swing中事件處理機制類似,隻是現在要使用的是com.google.gwt.user.client.ui中的類庫。
3 和Servlet的資料互動(參見:Developer Guide>Remote Procedure Calls)
運作在浏覽器中的應用程式通過Remote Service的概念和伺服器互動。
首先在用戶端的java代碼中,先定義自己的服務接口,這個接口要繼承com.google.gwt.user.client.rpc.RemoteService接口。
這個自動義的接口提供了可遠端調用的函數。以下是個例子:
public interface MyService extends RemoteService {
public String myMethod(String s);
}
函數的參數時要傳給遠端伺服器的參數,傳回值是遠端伺服器傳回的結果。
然後,要實作提供這個服務的Servlet。
這個Servlet要實作先前定義的服務接口。
而且要繼承自com.google.gwt.user.server.rpc.RemoteServiceServlet。當然RemoteServiceServlet繼承自HttpServlet。這個Servlet運作在web server上,例如tomcat。
public class MyServiceImpl extends RemoteServiceServlet implements
MyService {
public String myMethod(String s) {
// Do something interesting with 's' here on the server.
return s;
}
}
第三,定義異步接口。
“Ajax的核心是JavaScript對象XmlHttpRequest。該對象在Internet Explorer 5中首次引入,它是一種支援異步請求的技術。簡而言之,XmlHttpRequest使您可以使用JavaScript向伺服器提出請求并處理響應,而不 阻塞使用者。”
GWT支援的是這種異步請求機制。要實作這種異步請求機制,就要實作異步接口。
異步接口定義在用戶端。
異步接口的定義規則是:不需要繼承任何接口,名字是在自定義服務接口的名字後面添加Async字尾;接口中的方法與自定義服務接口方法同名,傳回值為void,參數在自定義服務接口方法參數的基礎上增加一個com.google.gwt.user.client.rpc.AsyncCallback類型的參數。
interface MyServiceAsync {
public void myMethod(String s, AsyncCallback callback);
}
第四,調用過程。
參考如下示例:
public void 調用函數() {
// (1) Create the client proxy. Note that although you are creating the
// service interface proper, you cast the result to the async version // of the interface. The cast is always safe because the generated proxy
// implements the async interface automatically.
//
MyServiceAsync myService = (MyServiceAsync) GWT
.create(MyService.class);
// (2) Specify the URL at which our service implementation is running.
// Note that the target URL must reside on the same domain and port from
// which the host page was served.
//
ServiceDefTarget endpoint = (ServiceDefTarget) myService;
endpoint.setServiceEntryPoint("/requestPath");
// (3) Create an async callback to handle the result.
//
AsyncCallback callback = new AsyncCallback() {
public void onSuccess(Object result) {
// do some UI stuff to show success
}
public void onFailure(Throwable caught) {
// do some UI stuff to show failure
}
};
// (4) Make the call. Control flow will continue immediately and later
// 'callback' will be invoked when the RPC completes.
//
myService.myMethod (“argument”, callback);
}
可以看到,遠端服務調用的過程是這樣的:
1 生成異步接口的對象。
2 定義遠端通路點。
3 建立AsyncCallback對象。
4 遠端調用。
實作異步接口的調用過程,不會阻塞使用者程序,會從函數中直接傳回;當使用者結果傳回時會由AsyncCallback對象對傳回結果做處理。
4 和Structs的整合
現在關于AJAX和Structs整合的文章在google, baidu上基本上搜尋不到。
如果Ajax用戶端向伺服器發請求和通過浏覽器向某Servlet發請求的機制一樣,可以用一個Action來實作3中提到的Servlet。
但伺服器結果傳回Ajax用戶端的的過程和普通Servlet響應傳回浏覽器的過程明顯不同,是以Structs的整合問題還有待進一步研究。