GWT配合使用Ant
我下载了GWT Linux Beta版本,并使用Java编写一个小应用程序,然后通过调用一个Ant构建文件在Tomcat 5.0的实例上编译和部署该应用程序。这个Ant文件调用GWT的Java-to-JavaScript编译器。该“编译器”是命令行脚本,它执行一个GWT java类把应用程序的Java代码转为JavaScript。
我们可以通过两种开发模式来使用GWT beta版:宿主模式和web模式。
宿主模式是指使用GWT内置的浏览器的中间开发步骤(在这种情况下,Java虚拟机使用GWT内置的浏览器运行GWT应用编译后的class内容);使用这个模式,编译后的代码仍然运行在Java虚拟机上(JVM)上。但是,我们这些Mac OS X操作系统的用户无法顺便使用Linux GWT的宿主模式。只要GWT的Mac OS X发布,宿主模式就可以使用了。
不同风格的Web开发
本文深入研究了GWT开发人员在为远程过程调用(PRCs)创建服务时可能会遇到的一些典型的web开发相关工作。PRCs是使用面向服务架构的应用程序的软件模型的一部分。这些开发工作包括:
•使用一个构建文件使开发和配置的步骤自动化,(这个构建文件调用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对象处理了plumbing。
应用程序中定义的每个服务都要有两个Java接口和一个Java类。为了编译这些类,你必须确保gwt-user.jar库在你的classpath中(有一个Ant文件将对此进行验证)。下面是定义服务的其中一个Java接口的代码示例。
| packagecom.parkerriver.gwt.testapp.client; importcom.google.gwt.user.client.rpc.RemoteService; publicinterfaceShowRespServiceextendsRemoteService{ StringdisplayResponse(Stringreq); } |
扩展GWT的RemoteService接口时需要这个服务接口。它定义了displayResponse()这一方法。
你同时还需要定义另外一个接口,客户端或者最终下载的JavaScript代码将使用它来调用上述的服务方法。GWT使用callback设计模式,这个我将在客户端代码中描述(请参考MyForm.java)。
| packagecom.parkerriver.gwt.testapp.client; importcom.google.gwt.user.client.rpc.AsyncCallback; publicinterfaceShowRespServiceAsync{ publicvoiddisplayResponse(Strings, AsyncCallbackcallback); } |
使用GWT定义服务需要一定的命名惯例;在服务接口名称 (ShowRespService)的末尾添加“Async”后缀。AsyncCallback对象是GWT API的一部分,它是为了处理客户端的服务响应。只要你看到代码就会明白它的具体操作。这些定义对象的Java代码是用于生成应用程序的客户端的JavaScript。
任何其他名字的Servlet
最后,你必须定义一个Java 类来实现远程服务接口。这个类是用在Ajax应用程序的服务器端。
| packagecom.parkerriver.gwt.testapp.server; importcom.parkerriver.gwt.testapp.client.ShowRespService; importcom.google.gwt.user.server.rpc.RemoteServiceServlet; importjava.util.Date; publicclassShowRespServiceImplextendsRemoteServiceServlet implementsShowRespService{ publicStringdisplayResponse(Stringreq){ if(req.length()<1){ thrownewIllegalArgumentException( "Blanksubmissionsfromtheclientareinvalid."); } StringBufferbuf=newStringBuffer("Yoursubmission:"); Datedate=newDate(); StringserverInfo=this.getServletContext().getServerInfo(); buf.append(req); buf.append("\n"); buf.append("Serverresponse:"); buf.append(date.toString()); buf.append("\n"); buf.append(serverInfo); returnbuf.toString(); } } |
这个类必须扩展RemoteServiceServlet——一个GWT API对象并且扩展了javax.servlet.http.HttpServlet。换句话说,你必须在servlet容器中配置这个类和它所实现的接口。
步骤
现在服务已经定义好了,让我们花一分钟的时间来看一下应用程序的目录结构。Google Web Toolkit包括一个命令行脚本——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> <!--InheritthecoreWebToolkitstuff.--> <inheritsname='com.google.gwt.user.User'/> <!--Specifytheappentrypointclass.--> <entry-pointclass='com.parkerriver.gwt.testapp.client.MyForm'/> </module> |
其他的文件和目录都是IntelliJ Web应用项目所必需包括的,有./classes、./WEB-INF和 ./gwtproj.ipr,因此你不需要专门花费精力在这些目录和文件上。
另外,./www目录只有当你运行GWT编译器生成应用程序代码时才会显示出来(除非是你自己创建的)。在我的项目中使用的是gwtproj.xml这个Ant文件和gwtproj.properties中定义的属性。在我展示Ant 构建文件之前,我们先看看MyForm.java 这个类,它是应用程序的入口点。


