使用GWT开发AJAX应用程序

简介:



一、 引言


  如果你是一个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验证程序(位于[url]http://validator.w3.org/[/url])。

在运行该验证程序后,我略微修改了一下该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的更多的探究刚刚开始,还依赖于广大读者的努力。

















本文转自朱先忠老师51CTO博客,原文链接: http://blog.51cto.com/zhuxianzhong/60112 ,如需转载请自行联系原作者

相关文章
|
6月前
|
JavaScript 前端开发 安全
安全开发-JS应用&原生开发&JQuery库&Ajax技术&加密编码库&断点调试&逆向分析&元素属性操作
安全开发-JS应用&原生开发&JQuery库&Ajax技术&加密编码库&断点调试&逆向分析&元素属性操作
|
5月前
|
XML 前端开发 API
颠覆传统!AJAX、Fetch API与Python后端,开启Web开发新篇章!
【7月更文挑战第14天】Web开发中,AJAX作为异步通信先驱,与新兴的Fetch API一起革新交互体验。Fetch基于Promise,简化了请求处理。Python后端,如Flask,提供稳定支撑。这三者的融合,推动Web应用达到新高度,实现高效、实时交互。通过示例展示,我们看到从发送请求到更新UI的流畅过程,以及Python如何轻松返回JSON数据。这种组合揭示了现代Web开发的潜力和魅力。
48 0
|
7月前
|
XML 前端开发 JavaScript
CSR(客户端渲染)和AJAX在Web开发中各自扮演不同的角色
【5月更文挑战第8天】CSR(客户端渲染)与AJAX在Web开发中各司其职。CSR提供初始HTML框架,通过JavaScript在浏览器端获取并渲染数据,提升交互性和响应速度。AJAX则实现页面局部更新,如实时搜索,不刷新页面即可获取数据。CSR可能因DOM操作多而引发性能问题,但可优化解决;AJAX适合频繁交互场景,提高响应性。两者在不同需求下各有优势,需按项目选择适用技术。
71 4
|
7月前
|
前端开发 JavaScript PHP
【PHP开发专栏】jQuery与PHP实现Ajax通信
【4月更文挑战第30天】本文介绍了使用jQuery和PHP实现Ajax通信的步骤。首先,讲解了Ajax的基础和jQuery简化Ajax操作的概念。接着,展示了如何使用jQuery的`$.get()`、`$.post()`和`$.ajax()`方法发送GET和POST请求,以及如何控制请求细节。在PHP端,讨论了接收和响应Ajax请求的方法,包括处理数据、设置响应类型和错误处理。结合jQuery与PHP,开发者能实现高效、无缝的异步数据传输,提升Web应用的用户体验。
135 1
|
7月前
|
前端开发 搜索推荐 安全
AJAX和CSR(客户端渲染)是Web开发中常用的两种技术
【5月更文挑战第8天】AJAX提升用户体验,减轻服务器压力,但对搜索引擎不友好且增加开发复杂度,易引发安全问题。CSR提供快速响应和交互性,改善用户体验,但首屏加载慢,搜索引擎支持不足,同样面临安全挑战。两者各有适用场景,需按项目需求选择。
63 0
|
7月前
|
XML 前端开发 JavaScript
【PHP 开发专栏】PHP 与 Ajax 交互开发
【4月更文挑战第30天】本文探讨了PHP与Ajax交互在Web开发中的应用。Ajax负责客户端的异步请求,PHP处理服务器端业务逻辑。两者结合实现高效、流畅的用户体验。文中阐述了Ajax的工作原理,PHP的角色,数据传输格式选择,并提供了发送Ajax请求、PHP处理请求的示例代码。实际应用包括实时数据更新、表单验证和动态内容加载。开发中需注意跨域、数据安全和性能优化。PHP与Ajax的结合将继续在Web开发中发挥重要作用。
95 0
|
7月前
|
设计模式 开发框架 前端开发
ajax应用设计模式,Ajax设计模式下Web开发的研究与应用
ajax应用设计模式,Ajax设计模式下Web开发的研究与应用
|
7月前
|
XML JSON 前端开发
ajax中get和post的区别,datatype返回的数据类型有哪些?web开发中数据提交的几种方式,有什么区别。百度使用哪种方式?
ajax中get和post的区别,datatype返回的数据类型有哪些?web开发中数据提交的几种方式,有什么区别。百度使用哪种方式?
61 0
|
Web App开发 JavaScript 前端开发
用jabsorb(json) for java编写AJAX应用程序
用jabsorb(json) for java编写AJAX应用程序 本文为原创,如需转载,请注明作者和出处,谢谢!jabsorb是一种基于Ajax/Web 2.0的简单轻便的框架,可用于在Web浏览中通过HTTP请求向服务端发送请求,并获得响应数据。

相关实验场景

更多