源文出自:https://txt.appspot.com/pt2club.blogspot.com/2010/02/gwt-part-2javascript-overlay-type.html
彻底了解 GWT Part 2:JavaScript 的 overlay type
原文:http://googlewebtoolkit.blogspot.com/2008/08/getting-to-really-know-gwt-part-2.html
技术校正、审阅:tkcn
假设你已经在 GWT module 当中,愉快地使用 JSNI 来呼叫某些手写的 JavaScript。一切运作正常,但是 JSNI 只能在独立的 method 下运作。某些整合性状况需要你彻底地把 JavaScript 跟 Java 的 object 绑在一起——写 DOM 跟 JSON 就是两个好例子——所以我们十分需要可以从 Java 程式码直接与 JavaScript object 互动的方法。换句话说,我们想要 JavaScript 的 object 看起来就像我们写的 Java object。
GWT 1.5 引入了 JavaScript overlay type,这让 GWT 程式整合各种 JavaScript object 变得容易许多。这个技术有很多好处,像是让你能用 Java IDE 的 code completion 跟 refactoring 功能,即使你写的是 untype 的 JavaScript object。
范例:简单、有效率的 JSON
用一个范例来了解 overlay type 是最简单的方法。假设我们要存取一组「customer」数据,底层是用 JSON object。在 JavaScript 中的资料结构可能像这样:
void jsonData = [
{ "FirstName" : "Ps", "LastName" : "Monkey" },
{ "FirstName" : "痞子", "LastName" : "猴" },
{ "FirstName" : "Pt2", "LastName" : "Club" },
{ "FirstName" : "STO", "LastName" : "Orz" },
];
要把一个 Java type 加到上述的资料结构,要从建立一个 JavaScriptObject 的 subclass 开始,这在 GWT 表示是一个 JavaScript 的 object。接著增加一些 getter。
// An overlay type
class Customer extends JavaScriptObject {
// Overlay types always have protected, zero-arg ctors
protected Customer() { }
// Typically, methods on overlay types are JSNI
public final native String getFirstName() /*-{ return this.FirstName; }-*/
public final native String getLastName() /*-{ return this.LastName; }-*/
// Note, though, that methods aren't required to be JSNI
public final String getFullName() {
return getFirstName() + " " + getLastName();
}
}
如此一来,GWT 就会了解所有 Customer 的 instance 实际上是来自 GWT module 以外的 JavaScript object。这包含了很多意义。举例来说,看到 getFirstName() 跟 getLastName() 里头的 this reference。它实质上是代表一个 JavaScript object,所以你操作这个 this 就像在 JavaScript 里头一样。在这个例子中,我们可以直接存取 JSON 中那些我们已知的 field:this.FirstName 跟 this.LastName。
那么,你要如何才能真正得到一个被包装成 Java type 的 JavaScript object 呢?你不能用 new Customer() 来建构它,因为重点是把一个既有的 JavaScript object 包装成 Java type。因此,我们必须使用 JSNI 来得到这样一个 object:
class MyModuleEntryPoint implements EntryPoint {
public void onModuleLoad() {
Customer c = getFirstCustomer();
// Yay! Now I have a JS object that appears to be a Customer
Window.alert("Hello, " + c.getFirstName());
}
// Use JSNI to grab the JSON object we care about
// The JSON object gets its Java type implicitly
// based on the method's return type
private native Customer getFirstCustomer() /*-{
// Get a reference to the first customer in the JSON array from earlier
return $wnd.jsonData[0];
}-*/;
}
现在来搞清楚我们做了啥。我们拿到了一个 plain old JSON object(译注:源自于 POJO)并且建立一个看起来很正常的 Java type,让 GWT 程式码中能够使用它。于是你就有了 code completion、refactoring、compile 阶段的检查——这些写 Java 时所拥有的好处。然而,你还是可以灵活地操作任何 JavaScript object,这使得存取 JSON service(使用 RequestBuilder)变得很轻而易举。
为一些 compiler 强者岔题一下。overlay type 另一个美妙的事情是你可以增加 Java 的 type,但是却不用影响底层的 JavaScript object。注意到上面例子中,我们加入的 getFullName() 这个 method。它是纯粹的 Java 程式码(并不存在于底层的 JavaScript object),但却是依照底层 JavaScript object 所写的。也就是说,处理同一个 JavaScript object,以 Java 的角度会比用 JavaScript 功能丰富得多;而且不用动到底层的 JavaScript object——无论是 instance 或是 prototype。
(接续上一段的题外话)在 overlay type 增加 method 这个很酷的怪招是可行的,因为 overlay type 的设计规则是不允许 polymorphic 呼叫,所有的 method 必须是 final 且/或 private。因此,compiler 是静态地解读每一个 overlay type 的 method,所以不需要在 runtime 的时候动态 dispatch。这是为什么我们不用拘泥在 object 的 function pointer;compiler 可以直接对 method 呼叫,就好像是 global function、独立于 object 之外。很明显的,直接呼叫 function 会比间接快得多。更棒的是,因为呼叫 overlay type 的 method 是静态解读担庑┒。
范例:lightweight collection
我们在上面的例子当中掩盖了某些事情。getFirstCustomer() 这个 method 是非常不切实际的。你一定会希望存取全部的 customer 阵列。所以,我们需要一个 overlay type 来表示这个 JavaScript 阵列。幸运的是,这很简单:
//泛型在 overlay type 裡頭也運作正常!
class JsArray<E extends JavaScriptObject> extends JavaScriptObject {
protected JsArray() { }
public final native int length() /*-{ return this.length; }-*/;
public final native E get(int i) /*-{ return this[i]; }-*/;
}
现在我们可以写出更有趣的程式了:
class MyModuleEntryPoint implements EntryPoint {
public void onModuleLoad() {
JsArray<Customer> cs = getCustomers();
for (int i = 0, n = cs.length(); i < n; ++i) {
Window.alert("Hello, " + cs.get(i).getFullName());
}
}
// Return the whole JSON array, as is
private final native JsArray<Customer> getCustomers() /*-{
return $wnd.jsonData;
}-*/;
}
这是一个很干净的程式码,尤其是以建立灵活配置的角度来看。正如上头提到的,compiler 可以作一些十分 fancy 的事情,让它相当有效率。看一下 onModuleLoad() 这个 method 在没有 obfuscate 的 compile 结果:
function $onModuleLoad(){
var cs, i, n;
cs = $wnd.jsonData;
for (i = 0, n = cs.length; i < n; ++i) {
$wnd.alert('Hello, ' + (cs[i].FirstName + ' ' + cs[i].LastName));
}
}
这个最佳化真的是 xx 的好。即使是 getFullName() 这个 method 的 overhead 也没了。事实上, 所有 Java method 的呼叫动作都不见了。当我们说:「GWT 给你可负担的 abstraction」,这就是其中之一。不仅 inline 的程式码执行速度明显变快、我们不再需要定义 function 的内容、也因而得以将 script 简短化(虽然持平而论,inline 的方式也很容易让 script 量变多,所以我们小心地在速度与程式码大小之间取得平衡)。现在回顾上头原始的 Java 程式码是十分有趣的,而试著推导 compiler 最佳化的步骤就展示到这边。 不过,我们还是忍不住要 show 一下对应、obfuscate 过的程式码:
function B(){var a,b,c;a=$wnd.jsonData;for(b=0,c=a.length;b<c;++b){ $wnd.alert(l+(a[b].FirstName+m+a[b].LastName))}}
注意在这个版本当中,唯一没有 obfuscate 的是 JavaScript 当中的识别字,例如 FirstName、 LastName、jsonData 等。这是为什么即使 GWT 努力让大量 JavaScript 交互沟通的操作变得容易,但我们还是努力说服别人尽量用纯 Java 来写程式、而不是混著 JavaScript 写。希望你听到我们讲这些之后,你会明白我们不是要打击 JavaScript——只是我们不能对它们最佳化,这会让我们很沮丧。
摻在一起作撒尿牛丸
overlay type 是 GWT 1.5 的重要特性。这个技术让直接与 JavaScript library 互相沟通变得相当容易。希望在读完这篇文章之后,你可以想像如何以一组 Java type 直接导入任何 JavaScript library 到 GWT 里头,进而使用 Java IDE 来进行高效率的开发跟 debug,却不会因为任何类型的 GWT overhead 而影响程式码大小或执行速度。同时,overlay type 作为一个强大的 abstraction 工具,提供更优雅的低阶 API,例如新的DOM package 。
分享到:
相关推荐
2. **编译时类型检查**:由于GWT使用Java,因此可以在编译时进行类型检查,避免了JavaScript常见的运行时错误,提高了代码的稳定性和可维护性。 3. **自动浏览器兼容性处理**:GWT编译器会生成针对不同浏览器的优化...
**GWT(Google Web Toolkit)** 是一个由Google开发的开放源代码JavaScript开发框架,它允许Java开发者使用Java语言来编写Web应用程序,并自动将其编译为优化过的JavaScript代码,从而在浏览器端运行。GWT提供了丰富...
Google Web Toolkit(GWT)是谷歌提供的一款开源工具,它允许开发者使用Java语言来编写Web应用程序,然后自动编译成优化过的JavaScript代码,以便在浏览器上运行。Eclipse是一款广泛使用的集成开发环境(IDE),而...
**GWT(Google Web Toolkit)** 是一个由Google开发的开放源代码JavaScript开发框架,它允许Java开发者使用Java语言编写Web应用程序,然后自动编译成优化的JavaScript代码。GWT进阶教程旨在帮助开发者深入理解并熟练...
gwt-maven-plugin 该插件旨在通过提供两种特定的打包方式: gwt-lib和gwt-app ,使使用Maven构建GWT项目更加容易。 基本用法 将插件添加到您的POM并启用扩展: < groupId>net.ltgt.gwt.maven</ groupId> ...
2. 客户端:使用GWT Java API编写,包括UI界面和业务逻辑,最终会被编译成JavaScript。 3. HTML/JavaScript:部署在Web服务器上的HTML页面,用于加载编译后的JavaScript应用。 4. CSS:定义应用的样式。 二、运行...
2. **Java-to-JavaScript编译**: 开发者可以使用Java语法编写GWT应用,这极大地简化了前端开发,因为Java开发者可以使用他们熟悉的工具和编程习惯。 3. **UI设计**: GWT提供了一种叫做Widget的机制,允许开发者创建...
2. **模块化(GWT Module)**:每个GWT项目都始于一个`.gwt.xml`模块文件,它定义了项目的配置信息,包括使用的库、本地化设置、主题等。 3. **Java到JavaScript编译**:GWT的编译过程将Java源代码转化为优化的...
**GWT(Google Web Toolkit)** 是一个由Google开发的开源JavaScript开发框架,它允许Java开发者使用Java语言来编写Web应用程序,并自动生成优化过的JavaScript代码。GWT的主要目标是简化复杂的Web开发过程,提高...
总之,这些学习资料和实例项目为初学者提供了全面了解和掌握GWT的途径。通过阅读Java和GWT应用开发的文档,可以构建理论基础;而通过实践Contact、StockWatcher和HelloMVP等示例项目,可以深入理解GWT的实战应用,...
`samples` 目录下的代码示例,如 `KitchenSink`,是了解和学习 GWT 功能的好资源。`KitchenSink` 展示了 GWT 提供的各种 UI 组件和功能。 5. **创建 GWT 项目**: 使用 `applicationCreator` 工具可以快速创建一...
**Cypal Studio for GWT** 是一个专为 **Eclipse IDE** 设计的插件,旨在简化基于 **Google Web Toolkit (GWT)** 的 **Ajax** 应用程序的开发流程。通过使用 GWT,Java 开发人员可以利用纯 Java 语言编写富互联网...
现在,该插件被认为是legacy GWT maven plugin (又名mojo GWT maven插件),而新插件被认为是new generation GWT maven plugin (又名tbroyer GWT maven插件)。 仍然支持旧版maven插件,但强烈建议将新插件用于新...
2. **自动编译**:GWT将Java代码编译为优化过的JavaScript,这使得应用程序在浏览器中的运行效率得到提高,并且能够支持各种浏览器,包括IE、Firefox、Chrome等。 3. **开发工具**:GWT提供了一个强大的集成开发...
GWT(Google Web Toolkit)是一个开源的Java开发框架,由Google公司开发,主要用于简化Web应用的开发。它允许开发者使用Java编写客户端的代码,然后通过GWT提供的编译器自动转换成浏览器可以执行的JavaScript和HTML...
GWT(Google Web Toolkit)是Google推出的一款开源的JavaScript开发框架,它允许开发者使用Java语言编写Web应用程序,并自动生成优化的JavaScript代码。RPC(Remote Procedure Call)是GWT中的一个核心特性,用于...
2. **Google Web Toolkit (GWT)**:GWT是一个开放源代码的Java开发工具,允许开发者使用Java语言编写客户端应用,然后编译成优化的JavaScript代码,可以在所有主流浏览器上运行。GWT提供了一套丰富的UI组件、异步...
- **案例2: GWT Shop**: - 开发一个简单的在线购物网站。 - 包括商品展示、购物车管理等功能。 - 使用GWT的UI组件构建用户界面,通过RPC实现与服务器的数据交互。 #### 五、总结 通过以上介绍可以看出,GWT提供...
gwt-2.7.0.part2.rar 官网下载最新版,提供给大家使用
### GWT开发文档详解 #### GWT概览 Google Web Toolkit (GWT),作为一款由谷歌推出的开源框架,旨在简化并加速复杂的JavaScript前端应用程序的构建与维护过程。它通过允许开发者使用熟悉的Java语言进行编码,随后...