简化 Ajax 和 Java 开发,第 1 部分: 用 JSP 标记文件动态生成 JavaScript 代码
基于简单开发的 JSP 标记文件构建可重用的 Ajax 和 Java 组件
Andrei Cioroianu, 高级 Java 开发人员和顾问, Devsphere
转自http://www.ibm.com/developerworks/cn/web/wa-aj-simplejava1/index.html
简介: 很多 Web 开发人员都经常抱怨说 Java? EE 太复杂、构建新的 Web 组件太难、定制现有的组件没有预想的那样简单,并且即便是很小的更改都需要重新启动应用程序。本系列给出了针对这些问题的解决方案,即采用代码生成器、约定、脚本语言和先进的 JavaServer Pages ? (JSP) 特性。在本文中,您将了解如何基于 JSP 标记文件构建可重用的 Ajax 和 Java 组件,而这些 JSP 标记文件很容易开发和部署。更改之后,JSP 标记文件会由 Java EE 服务器自动重编译,而无须重启应用程序。此外,您还能完全控制所生成的代码,并能轻松地定制这些轻量级组件,因为它们使用的是 JSP 语法。
本系列含 4 部分,展示了一种基于 JSP 的技术,用以生成 JavaScript 代码、显著减少需要手动编写的代码量,本文是第 1 部分。本文的示例应用程序展示了如何生成 JavaScript 函数来发送 Ajax 请求和处理 Ajax 响应。如果想要轻松地更改 Ajax 代码,可以将这里讨论的简单技巧应用到实际的应用程序中。本文更宽泛的目标是展示如何使用 JSP 标记文件针对具体需求生成 JavaScript 代码,而非只是 Ajax 例程。
使用框架和代码生成器
如果您很幸运地找到了一种能满足您需要的组件或框架,那么就请使用它吧。如果没有找到也没关系,因为您总是可以开发自己的解决方案,也可以定制现有的一段代码。不管是哪种情况,一种很好的做法是 “参数化” 代码并将其放入一个可重用的库,而非将参数硬编码到您的代码里。不过有时候,实现泛型并不实际,因为它会使开发变得复杂,而非简化。在将泛型代码放入可重用组件或框架时,可以考虑使用代码生成器来更有效地生成特定的代码。
在开发的过程中避免复制 & 粘贴
假设,您需要应用程序使用 Ajax 请求站点上的某些信息,最快的(当然不是最好的)方法是找到一些如清单 1 这样的免费代码、更改 URL 并将这些代码粘贴到 Web 页面。很多开发人员都会这么做,但这种做法会导致巨大的维护问题。如果应用程序具有数百个页面,最后的结果将是出现大量像清单 1 中的 getInfo() 这样的函数。不好的一面是每次需要进行添加或更改(比如实现 Ajax 请求的错误处理)时,您都必须要手动修改所有页面并重新测试它们。好的一面是您可以通过使用库、框架和代码生成器,很容易地避免这个维护问题。
清单 1. Ajax 函数
function getInfo(country, city) {
var request = null;
if (window.ActiveXObject)
request = new ActiveXObject("Microsoft.XMLHTTP");
else if (window.XMLHttpRequest)
request = new XMLHttpRequest();
else
return;
var url = "CityInfo.jsp?country=" + escape(country)
+ "&city=" + escape(city);
request.open("GET", url, true);
function processResponse() {
if (request.readyState == 4) {
if (request.status == 200) {
// ...
}
}
}
request.onreadystatechange = processResponse;
request.send(null);
}
开发泛型函数
一种好的开发实践是将尽量多的代码移入可重用的例程、函数、类或组件,而这些例程、函数、类或组件均能划分到库或框架中。在我们的示例中,您能找到一个泛型函数,此函数能创建 XMLHttpRequest 实例和调用实例的 open() 和 send() 方法。
假设您决定使用的函数的名称为 xhr(),它能接受 5 个参数:返回信息的页面的 URL、包含名称和请求参数的值的两个数组、HTTP 方法和用来处理 Ajax 响应的一个回调函数。现在,您的应用程序将会包含更为简单的函数,比如清单 2 中所示的 getInfo2(),而且代码也更容易维护。如果想要更改发送 Ajax 请求的代码,只能修改 xhr() 函数。
清单 2. 使用泛型函数
function xhr(url, paramNames, paramValues, method, callback) {
// send Ajax request ...
}
function getInfo2(country, city) {
function processResponse(request) {
// process Ajax response ...
}
xhr("CityInfo.jsp", ["country", "city"], [country, city],
"GET", processResponse);
}
清单 2 包含的泛型函数,名为 xhr(),特定于应用程序的函数名为 getInfo2()。泛型代码应被移入单独的 JavaScript 文件以便能将可重用函数导入需要它们的任何页面。对于特定的代码,比如 getInfo2() 函数,如果应用程序需要基于相同模式的很多函数,就应该考虑使用代码生成器。
动态生成代码
代码生成器能显著提高开发和维护 Web 应用程序的效率。比如,您可以使用 JSP、Java 代码或任何其他语言来从模板生成 JavaScript 函数。得益于属性名称,用来指定生成器参数的基于 XML 的语法能让代码可读性更好,也更容易理解。此外,标记属性没有像 JavaScript 函数或 Java 方法的参数那样的固定顺序。
对比起来,使用 XML 标记的一个明显优点就是它们能为属性使用默认值,然而编程语言只提供了有限的可能性来删除方法参数。请考虑这些关于代码生成器可扩展性的诸多方面,因为在不打乱现有代码的情况下向标记增加新的属性要比更改方法签名简单得多。使用 XML 和 JSP 的这些句法方面的优点是很明显的,尤其是当代码生成器需要大量属性的时候。
JSP 是在服务器端生成 JavaScript 代码的一种很好的选择,因为:
开发人员已经了解 JSP 语法。
JSTL 为条件及循环结构提供了标记。
JSP 页面让您可以很方便地生成任何形式的文本,包括 JavaScript 函数。
此外,JSP 技术已经有了一种很强大的机制来将可执行代码放在定制标记后面,所以,不必为基于 JSP 语法的模板实现解析器。最后,在每次您做更改时,也不需要外部工具来重新生成代码。
清单 3 中包含取自于本文下一章节所要展示的应用程序的一个代码片段。此处使用了一个名为 <da:xhr> 的定制的 JSP 标记来生成 getInfo3() 函数,当用户单击一个标签为 Get Info 的按钮时,该函数就会在 Web 浏览器中被调用。
清单 3. 使用 JSP 标记文件生成 Ajax 函数
<%@ taglib prefix="da" tagdir="/WEB-INF/tags/dynamic/ajax" %>
...
<script type="text/javascript">
<da:xhr function="getInfo3(country, city)" url="CityInfo.jsp" method="GET">
// process A