一、 引言
如果你是一个Java软件和Ajax开发者,那么,Google Web Toolkit(GWT)应该已经引起你的关注。
Google公司已经于2006年5月在Apache许可协议下发布了这种免费的开发工具包。GWT的设计目的是为了简化用Java语言开发Ajax应用程序。Google初始发行的beta版本可以适用于Windows和Linux平台,并许诺稍后要发行一个Mac OS X版本。
本文将探讨在Mac OS X上使用GWT和熟悉的Java工具,例如Apache Ant,Tomcat 5.0 servlet容器和IntelliJ IDEA集成开发环境开发一个简单的Ajax应用程序的完整过程。
注 本文假定读者具有一定的Java和Ant使用基础。
二、 与GWT一起使用Ant
我下载的 是GWT的Linux beta版本,并选用Java开发应用程序,然后使用一个Ant构建文件进行编译,最后在一个Tomcat 5.0实例上发布该应用程序。注意,这个Ant文件运行的是GWT Java-to-JavaScript编译器。其实,这个“编译器”只是一个执行一个GWT Java类的命令行脚本,该Java类负责为应用程序编写JavaScript。
使用GWT beta包括两种开发方式:主机方式和web方式。
主机方式是使用一个嵌入式的GWT浏览器和中间开发步骤;在这个方式中,你的编译代码继续运行于一个Java虚拟机(JVM)中。然而,主机方式无法应 用于我们这些使用Linux版本操作系统的Mac OS X用户。只有Google发行了一个Mac OS X版本,我们才可以使用主机方式。
三、 不同风格的Web开发
在创建远程过程调用(RPC)服务的同时,本文将详细讨论一些典型的GWT开发者可能面对的web开发有关的任务。RPC是一个软件模型的一部分,主要为使用面向服务的架构(SOA)的应用程序而设计。这些开发任务包括:
· 使用一个构建文件(构建运行GWT编译器,然后发布编译器的输出,并且把你的服务器端的Java类文件发布到一个servlet容器,例如Tomcat,Jetty或Resin)来自动化开发和发布步骤。
· 使用Firefox的DOM Inspector来观察由该GWT应用程序生成的HTML。
· 重新设置页面中的各部件而不必存取内在的HTML(既然你在使用GWT的Java API)。
· 确保HTML是有效的标记,例如,你的组织可能需要基于一个特别的XHTML文档类型。
四、 服务功能
首先,我将简短描述本文示例应用程序要创建的服务,设计这个示例是为了展示GWT使用的模型。
该应用程序在浏览器中显示一个表单,要求用户输入他们的姓名、年龄和原籍国家。当用户通过点按按钮提交表单时,该应用程序在一个文本域中显示一个服务器响应,而不必初始化一个页面刷新。图1显示了在Safari浏览器中该应用程序看上去的样子。
图1.一个由GWT生成的简单视图 |
图2:该应用程序用红色显示一条错误消息 |
五、 巧妙的服务机制
在Ajax应用程序中使用RPC可以消除显式地处理XMLHttpRequest和相关的服务器返回值的必要性,因为GWT对象能够为你处理复杂任务。
你的应用程序定义的每个服务都要求实现两个Java接口和一个Java类。为了编译这些类,你必须确保gwt-user.jar库位于你的classpath(由一个Ant文件入口负责实现这项任务)中。下列代码示例展示了定义我们的服务的Java接口。
package com.parkerriver.gwt.testapp.client; import com.google.gwt.user.client.rpc.RemoteService; public interface ShowRespService extends RemoteService{ String displayResponse(String req); } |
package com.parkerriver.gwt.testapp.client; import com.google.gwt.user.client.rpc.AsyncCallback; public interface ShowRespServiceAsync { public void displayResponse(String s,AsyncCallback callback); } |
package com.parkerriver.gwt.testapp.server; import com.parkerriver.gwt.testapp.client.ShowRespService; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import java.util.Date; public class ShowRespServiceImpl extends RemoteServiceServlet implements ShowRespService { public String displayResponse(String req) { if(req.length() < 1) { throw new IllegalArgumentException( "Blank submissions from the client are invalid."); } StringBuffer buf = new StringBuffer("Your submission: "); Date date = new Date(); String serverInfo = this.getServletContext().getServerInfo(); buf.append(req); buf.append("/n"); buf.append("Server response: "); buf.append(date.toString()); buf.append("/n"); buf.append(serverInfo); return buf.toString(); } } |
applicationCreator -out /Users/bruceperry/1gwt/secondapp/ com.parkerriver.gwt.testapp.client.MyForm |
图3:一个GWT和IntelliJ工程目录 |
图4.一个GWT应用程序的Java包和模块 |
<module> <!—继承核心Web Toolkit。--> <inherits name='com.google.gwt.user.User'/> <!--指定应用程序入口点类。--> <entry-point class='com.parkerriver.gwt.testapp.client.MyForm'/> </module> |
web.deploy.location=/users/bruceperry/parkerriver/gwt web.classes.location=/users/bruceperry/parkerriver/WEB-INF/classes |
<?xml version="1.0" encoding="UTF-8"?> <project name="gwtproj" default="all"> <property file="gwtproj.properties"/> <!—工程的顶级目录与ant文件存在的位置--> <dirname property="module.gwtproj.basedir" file="${ant.file}"/> <!--目录在顶级目录内的./classes--> <property name="gwtproj.output.dir" value= "${module.gwtproj.basedir}/classes"/> <!--这个目标调用MyForm-compile以创建./www目录下的所有的内容--> <target name="gwt-compile" depends= "compile.production.classes" description="use gwt's compiler"> <delete> <fileset dir="${web.deploy.location}" includes="**/*"/> </delete> <exec executable= "${module.gwtproj.basedir}/MyForm-compile" failοnerrοr="true"/> <copy todir="${web.deploy.location}"> <fileset dir= "${module.gwtproj.basedir}/www"> </fileset> </copy> </target> <target name="compile.production.classes" description= "Compile the gwtproj production classes"> <mkdir dir="${gwtproj.output.dir}"/> <javac destdir="${gwtproj.output.dir}" debug= "on" failοnerrοr="true" nowarn= "off" memoryMaximumSize="128m" fork= "true" executable="${module.jdk.home.gwtproj}/bin/javac"> <classpath refid="gwtproj.module.classpath"/> <src refid="gwtproj.module.sourcepath"/> </javac> </target> <!--把Java servlet类复制到web应用程序--> <target name="deploy.classes" depends="gwt-compile" description="copy classes to web directory"> <copy todir="${web.classes.location}"> <fileset dir="${gwtproj.output.dir}"> </fileset> </copy> </target> <target name="all" depends="deploy.classes" description="build all"/> </project> |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> |
图5:使用DOM Inspector观察后台实现内容。 |
//设置OK按钮单元格的垂直位置 grid.getCellFormatter().setVerticalAlignment(3,0, HasVerticalAlignment.ALIGN_TOP); |