用GWT实现基于Ajax的Web开发
来源:IBM Developerworks 简介:Google Web Toolkit (GWT) 是一个可以使用 Java 代码开发具有 Ajax 功能的应用框架。使用 GWT,开发人员可以更加高效地开发和部署主流 Web 应用程序。GWT Designer 是 Google 新推出的可视化开发插件,大大简化了界面开发工作。本文将结合 GWT Designer,以一个小型 Web 应用系统为例,对基于 GWT 的 Web 应用开发进行完整的介绍。包括开发环境的搭建、数据通信以及应用部署等方面。
GWT 简述以及 GWT 开发 Web 应用程序的优势 Ajax 及基于 Ajax Web 应用程序开发简述 Ajax 即“Asynchronous JavaScript and XML”(异步 JavaScript 和 XML),是一种创建交互式网页应用的网页开发技术。通过此技术,软件开发人员可以在最短的时间内开发出更小,更快的,更友好的 Web 应用系统。在传统的 web 应用中,用户填写并提交表单 (form),在提交表单时就向 web 服务器发送一个处理请求。服务器接收用户请求并处理传来的表单,并将结果以一个新的页面返回给用户。这种处理方式浪费了许多带宽,因为在前后两个页面中的大部分 HTML 代码往往是相同的。另外,由于每次交互都需要向服务器发送请求,交互的响应时间就依赖于服务器的响应时间,从而导致了用户界面的响应比本地应用程序慢得多。通过 Ajax 技术,使用 JavaScript 可以创建 XMLHttpRequest 对象来直接与服务器进行通信,在不重载页面的情况下完成与 Web 服务器的数据交换。由于在通讯的过程中传输的数据是开发人员可控制的有用数据,消除了冗余的 HTML 代码,减少了带宽占用,在很大程度上提高了 Web 应用系统的响应速度。另外,由于使用 XMLHttpRequest 对象作为后台通讯工具,页面不需要全部刷新,只需要刷新局部改变的数据,从而实现类似于桌面应用的效果。 使用 GWT 进行 Ajax Web 应用程序开发的优势 Google Web Toolkit(GWT)是 Google 公司推出的一款基于 Java 的 Ajax Web 应用程序开发框架。在此框架上,开发人员可以轻松的创建 Ajax Web 应用程序,而不必关注 JavaScript 的编写和调试,实现在浏览器中轻松地构建类似桌面应用般的程序。 使用面向对象的 Java 代替 JavaScript,大幅度提高了开发效率。 JavaScript 是一种脚本语言,它可以用来制作与网络无关的,用户交互复杂软件。它是一种基于对象 (Object Based) 和事件驱动 (Event Driver) 的编程语言。但是 JavaScript 无法实现真正的继承关系(注:使用放在 prototype 对象里,虽然可以实现两个实例对象中的数据共享,模拟继承,但这其实并不是真正的继承,更无法实现多层继承关系)。因此,使用 JavaScript 来完成 Ajax 开发,非常耗费时间,代码重复使用率低,难以调试,后期维护工作量巨大。 相比之下,Java 是一种真正的面向对象的语言。基于 Java 这一面向对象的语言,GWT 将真正的软件工程方法带入到 Ajax 应用程序开发当中。GWT 中提供了丰富的的基础组件,使开发人员从繁杂而又重复的 Ajax 构建工作中解放出来,更加专注于业务层和程序性能的优化。开发人员通过使用 GWT 可以快速地构建和维护复杂的、高性能的 JavaScript 应用程序。 GWT 提供了友好的界面,减少了 Web 应用程序的美化工作 由于通用的组件不够友好,导致 Web 开发的同时有大量的美化工作需要处理,所以以往的 Web 开发,都需要专业美工来协助完成。GWT 提供的丰富的组件库使用户可以很容易的开发出极具视觉享受的 UI 界面。如图 1 所示。 图 1. GWT 消息框
上图中为 Ext GWT 提供的消息框,下面为原始的消息框。通过比较可以看到,Ext GWT 的消息框明显更加友好。按照传统的 Web 开发方式要实现具有 Ext GWT 样式的消息框,还要付出相当一些额外的美化工作。而这只是一个非常简单的示例, GWT 所带来的具有友好界面体验的组件远不止此。 GWT Designer 简介 GWT Designer 是 Google 最新推出的,可以辅助开发者在 Eclipse 中快速构建 GUI 和 GWT/Java 应用的高效开视化开工具。使用 GWT Designer,开发人员只需通过简单拖拽可视化组件,即可完成组件的添加而无须繁琐的重复编码,同时使用 GWT Designer 也可以最大限度地完成布局管理等界面设计的工作。 基于 Eclipse 的 GWT 开发环境的搭建 Eclipse 是一个用 Java 开发的开源 IDE,由包括 IBM 在内的主要几家技术型公司所支持。使用 Eclipse 可以使开发者以高效的方式编写、组织、测试和调试软件。Eclipse 集成了对 GWT 脚本的支持,在 Eclipse 环境下使用 GWT 开发 Ajax Web 应用程序,无论是代码编写、组织、测试还是调试,都能够获得较高的生产力。基于 Eclipse 的 GWT 开发环境是业界公认的,最佳的 GWT 开发环境。 搭建 Eclipse 开发环境 搭建 Eclipse 开发环境很简单。只需要从http://www.eclipse.org/downloads/下载后解压即可使用。Eclipse 的版本很多,本文中将以 Eclipse Java EE IDE for Web Developers(Version: Helios Release) 为例进行说明。 搭建 GWT 开发环境 在 Eclipse 中安装 GWT,步骤如下: 选择 Eclipse 的菜单 Help | Install New Software …, 然后在 Work with 中输入http://dl.google.com/eclipse/plugin/3.6,在出现的列表中选择 Google App Engine Tools for Eclipse(required) 和 SDKs,之后点击”Next”并完成安装 。 安装完成后重启 Eclipse. 基于 Eclipse 的 GWT Designer 开发环境的搭建 搭建 GWT Designer 开发环境 在 Eclipse 中安装 GWT Designer,步骤如下: 选择 Eclipse 的菜单 Help | Install New Software …, 然后在 Work with 中输入http://dl.google.com/eclipse/inst/d2gwt/latest/3.6,在出现的列表中选择 GWT Designer 和 WindowBuilder Engine (required),之后点击按钮”Next”并完成安装 。 下载 Ext GWT(GXT)(http://www.sencha.com/products/extgwt/download/),解压后将其中相应的 jar(本例中选用的是 gxt-2.2.4-gwt2.jar)加入到 ClassPath 中。 建立带有 GWT Designer 支持的 Web 应用 GWT Designer 安装之后,就可以建立带有 GWT Designer 支持的 Web 应用了,建立此 Web 应用的步骤如下: 选择 Eclipse 的菜单 File | New | Other。弹出如图 2 所示的对话框。 图 2.创建 GWT Designer 支持的 Web 应用 在图2的对话框中选择 WindowBuilder | GWT Designer | Model | GWT Java Project。然后选择按钮”Next” ,将会弹出 Create a Java Project 对话框。 在 Create a Java Project 对话框中的 Project Name 中输入项目名称如 : EmployeeManagement,然后点击按钮”Next” ,将会弹出 New GWT Module 对话框: 在 New GWT Module 对话框中的 Module name 中输入 EmployeeManagement,在 Package name 中输入 com.employeemanagement。在 Configure for third-party toolkit 中选择 Ext GWT(GXT)。点击按钮”Finish” . 如果之前没有配置 Ext GWT(GXT) 的路径,此时会弹出一个对话框提示输入 GXT 的路径,这里直接选择已经下载的 GXT 包的存放路径即可。 GWT Designer 各组件简介及举例 带有 GWT Designer 支持的 Web 应用建立以后,右键点击所需编辑的类文件如 employeeViewer.java 类,然后选择菜单 Open With | GWT Designer。 在右面的区域中选择 Design 选项卡,就可以看到 GWT、 GXT 支持的所有组件,表1给出了常用的 GWT 和 GXT 组件。 表 1. GWT、GXT 常用组件列表
在 Designer 中可以很方便地使用这些组件,以下是一个使用 Button 按钮的例子。 在前面创建的例子中,右击类文件 EmployeeManagement.java 选择 Open With | GWT Designer. 在右面的 Tab 页中选择 Design 选项卡。 在 Palette 中选一个需要创建的组件,放在设计窗口上,本例中选择了 GXT 的 button 按钮,如图 3 所示。 图 3.创建 button 按钮 组件创建后可在 Properties 区域修改其样式属性,比如将 button 的标题改为 test。 图 4.修改 button 按钮的样式属性 添加事件处理代码 : 在 Properties 中选择显示按钮。然后,在事件列表中双击 ComponentSelected 事件,可以看到 Designer 已经创建好了此事件的外围代码,此时,光标也已经定位到 ComponentSelected 事件的代码上。接下来只需要根据实际情况添加具体的业务代码即可。 使用 Session Session 在交互中的作用 Web 应用是基于 HTTP 协议的,而 HTTP 协议是一种无状态协议。也就是说,用户从一个页面跳转到另一个页面时会重新发送一次 HTTP 请求,而服务端在返回响应的时候却无法获知该用户在请求当前页面之前都做了些什么。显然,HTTP 协议这样的限制根本无法满足 Web 应用对动态化的需求,于是 Session 便应运而生。使用 Session 可以存储特定用户会话所需的信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。 当用户请求来自应用程序的 Web 页时,如果该用户还没有 Session,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该 Session。可见,使用 Session 是 Web 开发中必不可少的。 Session 的使用 GWT 中的 RPC 机制可以直接使用 session,但要确保使用 session 的类继承自 com.google.gwt.user.server.rpc.RemoteServiceServlet,同时需要导入以下两个包:
之后就可以通过下面的方法设置或读取 session 中的信息了。 清单 1. 存取 Session 变量
2
3
4
5
6
7
8
|
HttpServletRequest request =
this
.getThreadLocalRequest();
HttpSession session = request.getSession();
// Set the variable USERNAME into session
session.setAttribute(
"USERNAME"
,”yuexiaopeng”);
// Get the variable USERNAME from session
String name = session.getAttribute("USERNAME”);
|
使用 RPC 实现与后台数据通信
作为 Ajax 的应用开发框架,GWT 使得实现客户端和服务器的通信变得十分简单,特别是异步通信,而这一功能就是通过 RPC 实现的。以下给出实现异步通信的具体步骤。
客户端定义同步服务接口
客户端用来定义异步通信的同步接口需要继承自 RemoteService。
清单 2.
import
com.google.gwt.user.client.rpc.RemoteService;
com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
@RemoteServiceRelativePath
(
"CheckUserService"
)
public
interface
CheckUserService
extends
RemoteService
{
boolean
checkUser(String userName,String passWord);
}
服务器端实现上述服务接口
清单 3.为了实现异步通信,在服务器端实现服务接口的类需要继承自 RemoteServiceServlet
com.google.gwt.user.server.rpc.RemoteServiceServlet;
class
CheckUserServiceImpl
RemoteServiceServlet
implements
CheckUserService
boolean
{
// Do related things
}
客户端定义上述服务的异步接口
在进行远程调用之前,还必须创建一个客户端的异步接口,而这个异步接口的定义要基于之前的同步接口并且和之前的同步接口同处一个客户端的包中。对于异步接口的方法而言,没有返回类型,参数列表中除了给出同步接口方法中的参数列表以外,还需要传入一个回调对象以便异步调用完成后通知该对象进行相应的处理。异步接口的命名则必须是同步接口名后加上 Async 后缀。
清单 4.
7
CheckUserServiceAsync
{
void
AsyncCallback<Boolean> callback);
在 web.xml 加上 Servlet 的配置信息
清单 5.
10
<servlet>
<servlet-name>CheckUserService</servlet-name>
<servlet-
class
>com.employeemanagement.server.login.service.CheckUserServiceImpl
</servlet-
>
</servlet>
<servlet-mapping>
<servlet-name>CheckUserService</servlet-name>
<url-pattern>/com.employeemanagement.EmployeeManagement/CheckUserService
</url-pattern>
</servlet-mapping>
客户端进行 RPC 调用
主要的接口和配置完成后,客户端就可以按照以下步骤来通过 RPC 实现和后台的异步通信:
● 使用 GWT.create()初始化服务接口 ;
●必要时,使用 ServiceDefTarget 为 Service 代理描述 Service 接入点的 URL ;
●创建一个异步回调对象以供 RPC 完成时调用;
●发出 RPC 请求。
有关 RPC 更多的介绍可以阅读参考资料。
远程调用的数据载体
远程调用时,客户端和服务器端往往要传递大量的信息,这就需要一种能包含各种数据的数据载体,比如 JSON 或 XML。当然也可以是用序列化的 Java 对象,但是对于夸应用的数据传输推荐使用公用的载体:JSON 或 XML。 以下简要介绍在 GWT 中如何使用 JSON 和 XML 进行数据的传输。
使用 JSON 传输数据
JSON 的全称是 JavaScript Object Notation,是一种轻量级的数据交换格式。JSON 与 XML 具有相同的特性,例如易于人工编写和阅读,易于机器生成和解析。但是采用 JSON 的数据传输比采用 XML 的数据传输具有更高的有效性。JSON 完全独立于编程语言,并且使用文本格式保存。关于 JSON 更多的了解请阅读参考资料。
在 GWT 中使用 JSON 作为数据传输格式的配置步骤如下:
1)在模块配置文件 .gwt.xml 中添加对 HTTP 和 JSON 的引用。
在 <inherits name=’com.google.gwt.user.User’/> 之后添加
<inherits name=”com.google.gwt.json.JSON”/>
2)在客户端 / 服务器端建立 JSON 数据并将其作为 RPC 的参数传输到另一端。
清单 6. 在客户端建立 JSON 数据
10
import
com.google.gwt.json.client.*
JSONObject jsonObject =
new
JSONObject();
JSONString value =
JSONString(
"yuexiaopeng"
);
jsonObject.put(
"name"
JSONArray arrayValue =
JSONArray();
arrayValue.
set
(
0
"item0"
));
1
"item1"
));
"array"
本例中建立的 JSON 数据如下:
1
{name:
"item"
}}
JSON 对象建立后,调用 JSONObject 的 toString() 方法将其转换为 String 做为 RPC 的一个参数,即可传到服务端。
3)在服务器 / 客户端解析 JSON 格式的数据。
清单 7. 在服务器端解析客户端传送的 JSON 数据
JSONObject jsonObject =
new
JSONObject(jsonBody);
String name = jsonObject.getString(
"name"
);
System.out.println(
"name is:"
+ name);
JSONArray jsonArray = jsonObject.getJSONArray(
"array"
);
for
(
int
i =
0
; i < jsonArray.length(); i++)
"item "
+ i +
" :"
+ jsonArray.getString(i));
这里 jsonBody 为服务器端从客户端接收到的包含 JSON 信息的字符参数。当然服务端也可根据需要建立 JSON 对象返回给客户端,然后客户端再做解析。
使用 XML 传输数据
XML(eXtensible Markup Language)为可扩展的标记语言,是一套定义语义标记的规则。用户可以根据实际需要定义自己的新的标记语言,并为这个标记语言规定其特有的一套标签。XML 易于阅读和编写,更重要的是其可以跨平台跨语言交换数据,使其成为在不同的应用间交换数据的理想格式。关于 XML 更多的了解请阅读参考资料。
在 GWT 中使用 XML 作为数据传输格式,其本质与使用 JSON 一样,需要以下几步 :
1)在模块配置文件 .gwt.xml 中添加对 HTTP 和 XML 的引用。
在 <inherits name=’com.google.gwt.user.User’/> 之后添加:
<inherits name =”com.google.gwt.xml.XML”/>
2)在客户端 / 服务器端建立 XML 数据并作为 RPC 的参数传输到另一端。
清单 8. 在服务器端建立 XML 数据
11
12
13
14
15
16
17
18
org.w3c.dom.*
Document xmlDoc =
DocumentImpl();
// create the root element
Element rootElement = xmlDoc.createElement(
"employees"
);
Element employeeItem = xmlDoc.createElement(
"employee"
employeeItem.setAttribute(
"ID"
"0008"
);
Element Name = xmlDoc.createElement(
);
Name.appendChild(xmlDoc.createTextNode(
"yuexiaopeng"
));
employeeItem.appendChild(Name);
rootElement.appendChild(employeeItem);
xmlDoc.appendChild(rootElement);
//convert XML object to string
Document document = rootElement.getOwnerDocument();
DOMImplementationLS domImplLS = (DOMImplementationLS) document.getImplementation();
LSSerializer serializer = domImplLS.createLSSerializer();
String result = serializer.writeToString(document);
清单 9. 本例中建立的 XML 数据
<employees>
<employee ID =
>
<name>
yuexiaopeng
</name>
</employee>
</employees>
3)在服务器 / 客户端解析 XML 格式的数据。
清单 10. 客户端解析接收到的 XML 数据
Document employeeDom = XMLParser.parse(xmlText);
Element employeeElement = employeeDom.getDocumentElement();
XMLParser.removeWhitespace(employeeElement);
NodeList employees = employeeElement.getElementsByTagName(
);
Element employee = (Element) employees.item(
);
NamedNodeMap attributes = employee.getAttributes();
Node attribute = attributes.getNamedItem(
);
String ID = attribute.getNodeValue();
String name = employee.getElementsByTagName(
).item(
).getFirstChild()
.getNodeValue();