AjaxTags 是由一系列的JSP标签组成的,这些标签用以简化Ajax应用的开发。对很多开发者而言,开发Ajax应用时总是从创建XMLHttpRequest对象开始――这是相当糟糕的行为,你在重复发明轮子,实际上,那个轮子已经有人帮你做好了!通过前面的介绍,我们知道有两种选择:一种是使用 JavaScript函数库来简化Ajax应用的开发,例如Prototype.js和Dojo等;另外一种是基于RPC的Ajax应用,例如DWR和 JSON-RPC-Java等。
AjaxTags则提供了更高层次的简化,它以 Prototype.js和其扩展项目Scriptaculous.js为基础,将常用的Ajax应用封装成简单的标签。通过使用 AjaxTags,J2EE程序开发者可以像使用普通标签一样来获得Ajax功能。虽然AjaxTags的灵活性相对较差,但对于大部分J2EE应用而言,常用的Ajax功能(如自动完成、级联菜单等)AjaxTags都有现成的实现,直接使用就可以了,所以我们没有理由拒绝AjaxTags。
18.1 AjaxTags的下载和安装
AjaxTags是属于sourceforge的一个开源项目,它以Prototype.js及相关项目为基础,提供了一套简单的JSP标签库(早期的AjaxTags还需要Struts的支持,但今天的 AjaxTags已经不再依赖于Struts了),通过这些标签库可以非常简单地开发出Ajax应用。
18.1.1 AjaxTags概述
AjaxTags是一套简单的JSP标签,这套标签以一些现有的开源项目为基础,AjaxTags最核心的依赖是Prototype.js库及其相关项目Scriptaculous.js。当然,JSTL和 jakarta-commons的一些包也是AjaxTags所必需的。除此之外,早期的AjaxTags还依赖于Struts框架,如果需要用 AjaxTags的displayTag标签,则还需要displayTag框架。
AjaxTags致力于解决J2EE应用开发者的软肋:厌倦了烦琐的JavaScript代码,以直接而烦琐的操作来操作DOM结构,从而提供HTML页面的动态显示。AjaxTags完全不需要开发者写一行 JavaScript代码,它以一种“非常Java的方式”来开发Ajax应用,因此它专属于J2EE应用,Ajax技术本身不局限于任何语言,但 AjaxTags只能用于Java平台。
只要开发者能使用简单的JSP标签,就可以使用AjaxTags。它提供了一组简单的标签,这些标签封装了常用的AjaxTags功能。
18.1.2 下载和安装AjaxTags
AjaxTags是属于sourceforge的一个开源项目,因此可以登录官方站点http://ajaxtags. sourceforge.net下载AjaxTags的最新版。目前,AjaxTags的最新版本是1.2 beta3,这是一个测试版,可能存在一定风险,但AjaxTags的产品版实在太老了,因此推荐使用AjaxTags 1.2 beta3版。
在浏览器的地址栏中输入http://sourceforge.net/project/showfiles.php?group_id=140499,即可下载到AjaxTags的1.2 beta3版本,将下载到的压缩文件解压缩,可看到如下文件结构。
css:该路径下包含了使用AjaxTags必需的CSS样式单,这些样式单文件管理Ajax页面最通用的显示效果。当然,用户可以开发自己的CSS样式单文件。
dist:该路径下包含了AjaxTags编译生成的JAR文件。
docs:该路径下存放AjaxTags的各种文档,但没有包含API文档(AjaxTags的API文档需要另行下载)。
images:该路径下包含使用AjaxTags必需的图片文件,这些图片文件用于生成Ajax页面中最通用的效果。当然,用户也可以使用自己喜欢的图片。
js:该路径下包含了使用AjaxTags必需的JavaScript库文件,例如prototype.js等文件都可以在该路径下找到。
lib:该路径下存放了编译和运行AjaxTags所依赖的第三方类库,用户可根据需要选择使用。
授权等其他相关文档。
要在一个Web应用中使用AjaxTags,只需要将其JAR文件复制到Web应用的WEB-INF\lib下就可以了。因为AjaxTags是一个专注表现层的技术,因此,如果需要在一个Web应用中使用 AjaxTags,则需要更多的东西。要在一个Web应用中使用AjaxTags,可以按如下步骤进行操作:
将AjaxTags项目解压缩路径下的dist/ajaxtags-1.2-beta3.jar复制到Web应用的WEB-INF/ lib下。
因为AjaxTags还需要第三方类库的支持,所以至少需要将JSTL项目的JAR文件和jakarta-commons下必需的JAR文件复制到WEB-INF/lib路径下。
因为需要使用JSP标签,所以对于使用JSP 1.1的用户,应该将ajaxtags.tld文件(该文件位于ajaxtags-1.2-beta3.jar文件的META-INF文件夹下)复制到 WEB-INF路径下,并在web.xml文件中定义标签库的引用,即在web.xml文件中增加如下一段:
<taglib>
<!-- 定义标签库的URI -->
<uri>/tags/ajax</uri>
<!-- 定义标签库TLD文件的物理位置-->
<location>/WEB-INF/ajaxtags.tld</location>
</taglib>
上面的配置文件是属于JSP自定义标签库的内容,请参考JSP自定义标签库的相关资料。上面的配置意味着在JSP页面中应使用如下代码来导入AjaxTags标签库:
<%@ taglib uri="/tags/ajax" prefix="ajax" %>
实际上,对于使用JSP 2.0的用户,根本不需要在web.xml文件中定义标签库,而可以直接在JSP页面中使用标签库的绝对地址,即通过如下方式引用AjaxTags的标签库:
<%@ taglib uri="http://ajaxtags.org/tags/ajax" prefix="ajax" %>
将AjaxTags项目解压缩路径下的js整个路径复制到Web应用的根路径下。当然,也可以放在Web应用的任意路径下,只要在JSP页面中能引用到这些JavaScript文件即可。AjaxTags通常依赖于如下4个关键的JavaScript库:
Prototype-1.4.0.js
Scriptaculous.js
Overlibmws.js
AjaxTags.js
因此,在每个JSP页面中都应该导入如下4行代码:
<script type="text/javascript" src="js/prototype-1.4.0.js"></script>
<script type="text/javascript" src="js/scriptaculous.js"></script>
<script type="text/javascript" src="js/overlibmws.js"></script>
<script type="text/javascript" src="js/ajaxtags.js"></script>
将 AjaxTags项目解压缩路径下的images文件夹复制到Web应用的根路径下。当然,也可以放在Web应用的任意路径下,只要在JSP页面中能引用到该路径下的图片文件即可。如果程序开发者决定使用自己的图片,则可以省略该步骤,但开发者应该自己提供相应的图片,例如自动完成应用中使用的转动图片。
将 AjaxTags项目解压缩路径下的css整个路径复制到Web应用的根路径下。当然,也可以放在Web应用的任意路径下,理由与images相似。同样,开发者也可以选择放弃AjaxTags默认的CSS样式,而使用自己的CSS样式。通常,我们可以使用如下格式来导入CSS样式:
<link type="text/css" rel="stylesheet" href="css/ajaxtags-sample.css" />
经过上面的步骤,我们就可以在一个JSP页面中使用AjaxTags标签了,这个标签可以极大地简化Ajax应用的开发。因为我们需要使用标签库,因此这些Ajax页面不能是普通的HTML页面,而必须是JSP页面。
使用AjaxTags的页面不能是静态的HTML页面,而必须是JSP页面。
当然,即使有AjaxTags的帮助,服务器的响应还是必须由程序员提供。下面,我们介绍如何开发服务器响应类。
18.2 AjaxTags入门
前面我们已经说过了:使用Ajax是相当简单的事情,完全不需要烦琐地创建XMLHttpRequest对象来发送Ajax请求。使用AjaxTags甚至不需要编写回调函数,不需要解析服务器响应,不需要程序员手动更新HTML页面显示,整个过程完全由AjaxTags完成,应用开发者只需要编写服务器响应即可。服务器响应就是Ajax请求的处理类。
18.2.1 编写处理类
这里说的处理类并不一定是一个完整的Java类,它可以是一个 JSP页面,也可以是一个配置在Web应用中的Servlet或者Struts的Action,甚至是一个非Java的服务器组件,只要它能响应用户的请求即可。当然,因为AjaxTags是一种高度封装的Ajax框架,因此处理类的返回值不能像之前那样随心所欲,而必须满足某种格式。服务器处理类的返回值必须满足如下XML文件格式:
<!-- XML文件的声明部分 -->
<?xml version="1.0" encoding="UTF-8"?>
<!-- AjaxTags服务器响应的根元素 -->
<ajax-response>
<!-- AjaxTags服务器响应的内容必须在response里 -->
<response>
<!-- 下面的item节点分别用于不同的选择 -->
<item>
<name>Record 1</name>
<value>1</value>
</item>
<item>
<name>Record 2</name>
<value>2</value>
</item>
<item>
<name>Record 3</name>
<value>3</value>
</item>
</response>
</ajax-response>
当然,也可以使用普通文本响应,使用普通文本响应则应该生成如下格式的响应:
#普通文本响应的示范
#每项响应对应一行,每行的前面部分是name,后面是value
#中间以英文逗号隔开
Record 1,1
Record 2,2
Record 3,3
下面介绍的是一个简单应用,以自动完成为示范建立一个对应的处理类,处理类以JSP来代替。下面是自动完成的处理JSP页面代码。这是一个简单的级联菜单应用,用户一旦选中第一个下拉列表框的某个选项值,下一个下拉列表框将随之变化。处理类由一个JSP页面充当,该页面负责生成一个XML响应,而XML响应则符合上面的格式。下面是该处理器页面的代码:
<%@ page contentType="text/html; charset=GBK" language="java" %>
<%@ page import="java.util.*"%>
<%
//获取请求参数
int country = Integer.parseInt(request.getParameter("country"));
//设置响应的页面头
response.setContentType("text/xml; charset=UTF-8");
//控制响应不会在客户端缓存
response.setHeader("Cache-Control", "no-cache");
//用于控制服务器的响应
List<String> cityList = new ArrayList<String>();
//根据请求参数country来控制服务器响应
switch(country)
{
//对于选择下拉框的“中国”选项
case 1:
cityList.add("广州");
cityList.add("深圳");
cityList.add("上海");
break;
//对于选择下拉框的“美国”选项
case 2:
cityList.add("华盛顿");
cityList.add("纽约");
cityList.add("加州");
break;
//对于选择下拉框的“日本”选项
case 3:
cityList.add("东京");
cityList.add("大阪");
cityList.add("福冈");
break;
}
%>
<ajax-response>
<response>
<%
//遍历集合,依次将城市添加到服务器响应的item项里
for(String city : cityList)
{
%>
<item>
<name><%=city%></name>
<value><%=city%></value>
</item>
<%}%>
</response>
</ajax-response>
该页面根据请求参数,依次将3个城市添加到cityList集合里,然后通过如下代码表示生成的页面是一个XML文件:
response.setContentType("text/xml; charset=UTF-8");
一旦生成了XML响应,就可以在客户端JSP页面使用标签来生成Ajax响应了。
18.2.2 使用标签
在客户端页面使用AjaxTags标签是非常简单而且“非常Java”的,几乎感觉不到使用了Ajax功能,但该页面已经具有了Ajax能力。在JSP页面使用AjaxTags应按如下步骤进行:
在JSP页面中使用taglib导入AjaxTags标签库。
在JSP页面中导入AjaxTags必需的JavaScript库。
使用AjaxTags对应的标签。
使用AjaxTags的select标签的JSP页面代码如下:
<!-- 导入AjaxTags标签库 -->
<%@ taglib uri="http://ajaxtags.org/tags/ajax" prefix="ajax" %>
<!-- 设置页面的内容以及对应的编码集 -->
<%@ page contentType="text/html;charset=GBK"%>
<html>
<head>
<title>第一个AjaxTags应用</title>
<!-- 在JSP页面中引入必需的JavaScript库 -->
<script type="text/javascript" src="js/prototype-1.4.0.js"></script>
<script type="text/javascript" src="js/scriptaculous.js"></script>
<script type="text/javascript" src="js/overlibmws.js"></script>
<script type="text/javascript" src="js/ajaxtags.js"></script>
<!-- 在JSP页面中引入必需的CSS样式单 -->
<link type="text/css" rel="stylesheet" href="css/ajaxtags-sample.css" />
</head>
<body>
国家:
<!-- 激发Ajax的源select元素 -->
<select id="country" name="country">
<option value="">选择一个国家</option>
<option value="1">中国</option>
<option value="2">美国</option>
<option value="3">日本</option>
</select>
城市:
<!-- 显示Ajax响应的select元素 -->
<select id="city" name="city">
<option value="">城市列表</option>
</select>
<!-- 使用AjaxTags标签 -->
<ajax:select
baseUrl="res.jsp"
source="country"
target="city"
parameters="country={country}" />
</body>
</html>
在上面的JSP页面中,除了引入几个JavaScript代码库外,完全不需要任何JavaScript代码,丝毫感受不到使用Ajax的痕迹,但因为使用了AjaxTags的select标签(该标签用于生成级联菜单的Ajax应用),该页面也具有了级联菜单的功能。图18.1显示了使用AjaxTags后该页面的级联菜单效果。
图18.1 使用AjaxTags后级联菜单的效果
通过在JSP页面中使用AjaxTags标签,可以看到AjaxTags标签使Ajax应用非常简单。
因为有些浏览器在处理以GET方式发送的请求时存在一些问题,因此这里修改了ajaxtags.js文件中的请求发送方式。关于请求的发送方式,笔者更倾向于使用POST请求,而AjaxTags默认的请求发送方式是GET。只需打开ajaxtags.js文件,将文件中的method: 'get'替换成method: 'post',即可改变AjaxTags的请求发送方式。
18.3 处理类的几种形式
前面已经介绍过了,AjaxTags的处理类并不一定是一个真正的 Java类,它可以有很多形式,甚至于可以是一个非Java文件,唯一的要求是该处理类能返回一个满足格式的XML文件。除此之外,AjaxTags还提供了几个特殊的类,这些特殊的类可以简化处理类的实现。
下面依次介绍处理类的几种形式,介绍这几种形式时都以前面介绍的级联菜单应用为基础,应用使用AjaxTags标签的JSP页面没有太大改变,仅改变了ajax:select标签的baseUrl属性――这是因为采用不同处理类时,处理类在服务器端配置的URL不同。