一、 引言
如果你是一个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浏览器中该应用程序看上去的样子。
例如,当用户保留一个文本框为空而点击ok,submit按钮时将显示出图2所示结果。
五、 巧妙的服务机制
在ajax应用程序中使用rpc可以消除显式地处理xmlhttprequest和相关的服务器返回值的必要性,因为gwt对象能够为你处理复杂任务。
你的应用程序定义的每个服务都要求实现两个java接口和一个java类。为了编译这些类,你必须确保gwt-user.jar库位于你的classpath(由一个ant文件入口负责实现这项任务)中。下列代码示例展示了定义我们的服务的java接口。
这个服务接口要求扩展gwt接口remoteservice。它定义了单个方法displayresponse()。
另外,你还必须定义一个客户端(或使用最终下载的javascript代码)用于调用这个服务方法的接口。当我显示客户端代码时(请参考myform.java),该gwt使用一个我描述的回调设计模式。
这个asynccallback对象负责(作为gwt api的一部分)为客户端处理服务响应。
六、 一个servlet
最后,你必须定义一个实现远程服务接口的java类。这个类将位于你的ajax应用程序的服务器端。
这个类必须继承remoteserviceservlet(这是本身继承自javax.servlet.http.httpservlet的一个gwt api对象)。也就是说,这个类及其实现的接口必须被发布到你的servlet容器中。
七、 步骤
现在,既然定义了服务,那么让我们来回顾一个这个应用程序的目录结构。gwt包括一个命令行脚本applicationcreator,它能够为你生成一个框架性的工程目录结构。在你解压下载的gwt后,你会在顶级目录下发现该applicationcreator。我使用下列命令行作为开始:
图3展示了该目录看上去的样子。
applicationcreator生成./src目录以及myform-compile和myform-shell脚本。我的ant文件执行的是myform-compile;另一个脚本将在gwt模式下启动主机方式。这个./src目录中包括了嵌套的目录以匹配你的包名,如图4所示。
myform.gwt.xml文件是一个生成的配置文件,它其实是gwt调用的一个“模块”。它指定描述你的应用程序“入口点”的java类(这是一个类似于一个包含一个main()方法的java类)。
其它的文件或目录,包括./classes、./web-inf和./gwtproj.ipr,都是一个intellij web应用程序工程的必要组成部分;因此,你不必特别注意它们。
另外,直到生成你的应用程序代码的gwt编译器时,./www目录才出现(除非你自己创建它)。我的工程使用了ant文件gwtproj.xml,还有定义在gwtproj.properties中的属性。在我向你展示ant构建文件前,我们先来看一下描述应用程序入口点的myform.java类。
八、 入口点
这个myform.java类实现了gwt api接口entrypoint;因此,该类必须实现onmoduleload()方法,当浏览器加载你的ajax应用程序时此方法为浏览器的javascript引擎所调用。
也就是说,gwt编译器把这个类编译成javascript代码。myform.java类为浏览器视图建立表单widget。该类还决定了点击ok和submit按钮时用户的响应。代码中的注释已经作了详细的描述,所以在此不再多言。
注意,这个类中的大部分代码是处理gwt api。有意思的是,如果你必须实现javascript dom编程(就象在showrpcstatus()方法中所展示的),那么你可以用java来实现com.google.gwt.user.client.dom类。
九、 构建文件
下面是ant构建文件的主要功能;这个构建文件:
1. 把java文件编译到工程目录的./classes目录下。
2. 执行gwt编译脚本(在这个例子中是myform-compile)。
3. 把在./www目录下生成的结果代码移动到一个较大的已经发布到tomcat上的web应用程序。
4. 把编译的java servlet及相关接口(showrespservice)复制到同一个web应用程序下。
注意,这里的两个目标:编译java类和初始化到javascript的转换有可能使整个构建过程失败,如果期间发生任何错误的话。
十、 ant xml
下面是gwtpoj.properties文件包含的内容(省略了其它的内容):
下列xml描述了刚才的ant文件的主要功能:
然后,我把myform.html上传到www协会的htm验证程序(位于http://validator.w3.org/)。
在运行该验证程序后,我略微修改了一下该html,例如适当关闭meta标签并且把一个type="text/javascript"添加到脚本标签。
然而,如果你想满足xhtml strict标准,那么还需要进行更为复杂的修改。例如,w3c的验证程序将把iframe标签显示为“undefined element”,而这个标签是gwt的历史支持功能(提供与一个浏览器back按钮相同的功能)必需的。xhtml strict中已经删除了iframe元素。
这个对你来说可能不是个问题(可能会在gwt的未来版本中得到解决,还有任何其它明显的问题);然而,你还可以实现其它可选策略,例如扩展gwt的类并创建你自己的兼容widget等。
十三、 位置对齐问题
一个在web开发中普通存在的问题就是应用程序的可视化设计问题。工程的设计者可能想使页面看上去如其在adobe illustrator创建一样的效果,对不对?
尽管当你开发一个复杂的ajax工程时你可能无法实现这种理想的视觉效果;但是,你至少可以使用firefox的dom inspector来观察你的java类最终生成的html。然后,再从这里进行修改。
例如,转到firefox的“tools=>dom inspector”菜单项(见图5)。
上图显示了,你在java代码中使用的com.google.gwt.user.client.ui.grid对象被实现为一个html table标签。这个table中的包含ok,submit按钮的td标签与一个style属性(其值为"verticle-align:top")相关联。
下面是在myform.java类中相关的初始化适当格式的java代码:
如果在代码中不进行这个调用,那么该按钮可能会在文本域的中间部分上下浮动。
十四、 总结
google公司发布的google web toolkit(gwt)已经引起业界的普遍关注。既然gwt的设计目的是为了简化用java语言开发ajax应用程序,而ajax是web 2.0时代的技术基础,所以gwt发行所引起的轰动应该在意料之中。
本文仅给出使用gwt和熟悉的java工具开发一个简单的ajax应用程序的示例,而有关gwt的更多的探究刚刚开始,还依赖于广大读者的努力。
如果你是一个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生成的简单视图 |
例如,当用户保留一个文本框为空而点击ok,submit按钮时将显示出图2所示结果。
![]() 图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); } |
这个服务接口要求扩展gwt接口remoteservice。它定义了单个方法displayresponse()。
另外,你还必须定义一个客户端(或使用最终下载的javascript代码)用于调用这个服务方法的接口。当我显示客户端代码时(请参考myform.java),该gwt使用一个我描述的回调设计模式。
| package com.parkerriver.gwt.testapp.client; import com.google.gwt.user.client.rpc.asynccallback; public interface showrespserviceasync { public void displayresponse(string s,asynccallback callback); } |
这个asynccallback对象负责(作为gwt api的一部分)为客户端处理服务响应。
六、 一个servlet
最后,你必须定义一个实现远程服务接口的java类。这个类将位于你的ajax应用程序的服务器端。
| 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(); } } |
这个类必须继承remoteserviceservlet(这是本身继承自javax.servlet.http.httpservlet的一个gwt api对象)。也就是说,这个类及其实现的接口必须被发布到你的servlet容器中。
七、 步骤
现在,既然定义了服务,那么让我们来回顾一个这个应用程序的目录结构。gwt包括一个命令行脚本applicationcreator,它能够为你生成一个框架性的工程目录结构。在你解压下载的gwt后,你会在顶级目录下发现该applicationcreator。我使用下列命令行作为开始:
| applicationcreator -out /users/bruceperry/1gwt/secondapp/ com.parkerriver.gwt.testapp.client.myform |
图3展示了该目录看上去的样子。
![]() 图3:一个gwt和intellij工程目录 |
applicationcreator生成./src目录以及myform-compile和myform-shell脚本。我的ant文件执行的是myform-compile;另一个脚本将在gwt模式下启动主机方式。这个./src目录中包括了嵌套的目录以匹配你的包名,如图4所示。
![]() 图4.一个gwt应用程序的java包和模块 |
myform.gwt.xml文件是一个生成的配置文件,它其实是gwt调用的一个“模块”。它指定描述你的应用程序“入口点”的java类(这是一个类似于一个包含一个main()方法的java类)。
| <module> <!―继承核心web toolkit。--> <inherits name='com.google.gwt.user.user'/> <!--指定应用程序入口点类。--> <entry-point class='com.parkerriver.gwt.testapp.client.myform'/> </module> |
其它的文件或目录,包括./classes、./web-inf和./gwtproj.ipr,都是一个intellij web应用程序工程的必要组成部分;因此,你不必特别注意它们。
另外,直到生成你的应用程序代码的gwt编译器时,./www目录才出现(除非你自己创建它)。我的工程使用了ant文件gwtproj.xml,还有定义在gwtproj.properties中的属性。在我向你展示ant构建文件前,我们先来看一下描述应用程序入口点的myform.java类。
八、 入口点
这个myform.java类实现了gwt api接口entrypoint;因此,该类必须实现onmoduleload()方法,当浏览器加载你的ajax应用程序时此方法为浏览器的javascript引擎所调用。
也就是说,gwt编译器把这个类编译成javascript代码。myform.java类为浏览器视图建立表单widget。该类还决定了点击ok和submit按钮时用户的响应。代码中的注释已经作了详细的描述,所以在此不再多言。
注意,这个类中的大部分代码是处理gwt api。有意思的是,如果你必须实现javascript dom编程(就象在showrpcstatus()方法中所展示的),那么你可以用java来实现com.google.gwt.user.client.dom类。
九、 构建文件
下面是ant构建文件的主要功能;这个构建文件:
1. 把java文件编译到工程目录的./classes目录下。
2. 执行gwt编译脚本(在这个例子中是myform-compile)。
3. 把在./www目录下生成的结果代码移动到一个较大的已经发布到tomcat上的web应用程序。
4. 把编译的java servlet及相关接口(showrespservice)复制到同一个web应用程序下。
注意,这里的两个目标:编译java类和初始化到javascript的转换有可能使整个构建过程失败,如果期间发生任何错误的话。
十、 ant xml
下面是gwtpoj.properties文件包含的内容(省略了其它的内容):
| web.deploy.location=/users/bruceperry/parkerriver/gwt web.classes.location=/users/bruceperry/parkerriver/web-inf/classes |
下列xml描述了刚才的ant文件的主要功能:
| <?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" failonerror="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" failonerror="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> |
你可以从ide(在intellij中)中或在包含该构建文件的目录下使用下列命令行来运行这个ant文件:
ant -buildfile gwtproj.xml
大部分情况下,在修改应用程序和运行ant后,你都可以通过重载浏览器页面而在浏览器中看到这些变化。
十一、 安装
注意,在安装时,你必须把gwt-user.jar库添加到你的web应用程序的/web-inf/lib目录下。
我把创建的jar文件,还有javax包(gwt-user-deploy.jar)都添加到/web-inf/lib目录下。这是因为tomcat不会加载单个的web应用程序的库文件,如果它已经包含servlet api类的话。
十二、 难点
applicationcreator还会为你创建ajax应用程序的html前端,在这个例子中是myform.html。
如果你的应用程序的htm必须满足一种标准(例如xhtml transitional 或strict),那么该怎么办呢?对于xhtml transitional,我首先把要求的doctype添加到myform.html的顶部以及该html标签的相关属性中:
| <!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"> |
然后,我把myform.html上传到www协会的htm验证程序(位于http://validator.w3.org/)。
在运行该验证程序后,我略微修改了一下该html,例如适当关闭meta标签并且把一个type="text/javascript"添加到脚本标签。
然而,如果你想满足xhtml strict标准,那么还需要进行更为复杂的修改。例如,w3c的验证程序将把iframe标签显示为“undefined element”,而这个标签是gwt的历史支持功能(提供与一个浏览器back按钮相同的功能)必需的。xhtml strict中已经删除了iframe元素。
这个对你来说可能不是个问题(可能会在gwt的未来版本中得到解决,还有任何其它明显的问题);然而,你还可以实现其它可选策略,例如扩展gwt的类并创建你自己的兼容widget等。
十三、 位置对齐问题
一个在web开发中普通存在的问题就是应用程序的可视化设计问题。工程的设计者可能想使页面看上去如其在adobe illustrator创建一样的效果,对不对?
尽管当你开发一个复杂的ajax工程时你可能无法实现这种理想的视觉效果;但是,你至少可以使用firefox的dom inspector来观察你的java类最终生成的html。然后,再从这里进行修改。
例如,转到firefox的“tools=>dom inspector”菜单项(见图5)。
![]() 图5:使用dom inspector观察后台实现内容。 |
上图显示了,你在java代码中使用的com.google.gwt.user.client.ui.grid对象被实现为一个html table标签。这个table中的包含ok,submit按钮的td标签与一个style属性(其值为"verticle-align:top")相关联。
下面是在myform.java类中相关的初始化适当格式的java代码:
| //设置ok按钮单元格的垂直位置 grid.getcellformatter().setverticalalignment(3,0, hasverticalalignment.align_top); |
如果在代码中不进行这个调用,那么该按钮可能会在文本域的中间部分上下浮动。
十四、 总结
google公司发布的google web toolkit(gwt)已经引起业界的普遍关注。既然gwt的设计目的是为了简化用java语言开发ajax应用程序,而ajax是web 2.0时代的技术基础,所以gwt发行所引起的轰动应该在意料之中。
本文仅给出使用gwt和熟悉的java工具开发一个简单的ajax应用程序的示例,而有关gwt的更多的探究刚刚开始,还依赖于广大读者的努力。





闽公网安备 35060202000074号