在你开始前
关于本教程
在本教程中,我们解释了如何基于带有XML或Ajax的异步JavaScript开发和设计Web应用程序。 您将构建一个示例的基于Web的图书订购应用程序 ,该应用程序提供实时验证和页面刷新,以实现高效,流畅的用户交互。
先决条件
我们将使用Tomcat运行Ajax应用程序。 Tomcat是Servlet容器,用于Java Servlet和JavaServer Pages技术的官方参考实现。 下载jakarta-tomcat-5.0.28.exe并运行它以将Tomcat安装到您想要的任何位置-例如,c:\ tomcat5.0。
下载本教程的源代码和Web应用程序 (在wa-ajax-Library.war中)。
Ajax简介
Ajax基础
Ajax带来了动态,异步的Web体验,而无需刷新页面。 它包含以下技术:
- XHTML和CSS提供了基于标准的演示。
- 文档对象模型(DOM)提供动态显示和交互。
- XML和XSLT提供数据交换和操作。
-
XMLHttpRequest
提供异步数据检索。 - JavaScript将所有内容绑定在一起。
Ajax技术的核心是一个JavaScript对象: XMLHttpRequest
。 该对象是通过浏览器实现提供的-首先通过Internet Explorer 5.0,然后通过与Mozilla兼容的浏览器。 靠近这个物体。
XMLHttpRequest
使用XMLHttpRequest
,您可以使用JavaScript向服务器发出请求并处理响应,而不会阻塞用户。 当您创建网站并使用XMLHttpRequest
在客户端的浏览器上执行屏幕更新而无需刷新时,它提供了很大的灵活性和丰富的用户体验。
XMLHttpRequest
应用程序的示例包括Google的Gmail服务,Google的“建议”动态查找界面和MapQuest动态地图界面。 在接下来的部分中,我们将在演示书订单应用程序的设计和实现时详细演示如何使用XMLHttpRequest
对象。
应用设计
应用程序的要素
基于Web的订购示例应用程序将包含以下在Ajax中实现的客户端功能:
- 订阅ID验证
- 查看作者列表
- 查看发布者列表
此处的目的是显示Web页面中的实时验证和页面刷新如何使用户交互更加流畅和高效。
应用程序的结构
图1. Ajax架构

该应用程序将是使用JavaServer Pages(JSP)技术开发的单个Web页面。 用户将能够使用Web浏览器(例如Microsoft®Internet Explorer)来调用网页,并输入应用程序实时验证的订阅ID 。 由于ID是异步验证的,因此用户可以输入更多信息。 用户可以按作者或出版者查看书籍标题。 屏幕将根据用户选择填充“ 作者或发布者”列表 。 根据选择,将填充“ 标题”列表 。 所有这些列表将实时填充-换句话说,页面不会刷新,但是数据仍然来自后端层。 我们称这种现象为实时刷新 。
如您在图1中所看到的, XMLHttpRequest
JavaScript对象有助于实时异步处理。 此对象通过HTTP以XML的形式向驻留在Web容器中的LibraryServlet
Servlet发出请求。 然后,该Servlet查询数据库,获取数据,然后再次以XML over HTTP的形式将其发送回客户端。 请求和响应是实时发生的,无需刷新页面。
这就是使Ajax如此强大的原因。 用户不等待页面重新加载完成,因为没有页面重新加载。
在下一节中 ,我们将演示如何基于此设计实现图书订购应用程序。 我们将带您遍历代码并进行一些分析。 (要获取本教程的示例代码,请下载文件x-ajax-library.war 。)
实施应用
使用Ajax实现应用程序
在本节中,我们对示例书订购应用程序进行了代码演练,并仔细研究了每个基于Ajax的Javascript组件:
- 验证订阅ID
- 查看作者
- 查看发布者
- 查看标题
代码演练:验证订阅ID
让我们从功能Validate Subscription ID <input type="text" name="subscriptionID" onblur="validate(this.form)"/>
。 此代码创建一个文本字段,用户可以在其中输入Subscription ID 。 用户输入ID并移至表单中的下一个字段后,就会触发onBlur
事件。 此事件调用JavaScript函数validate()
:
var req;
function validate(formObj) {
init();
req.onreadystatechange = subscriptionValidator;
req.send("subscriptionID=" + formObj.subscriptionID.value);
}
validate()
函数将formObj
作为参数。 它首先调用init()
函数:
function init() {
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
}
var url = "/Library/LibraryServlet";
req.open("POST", url, true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
}
代码演练:init()
现在看一下init()
函数的功能(我们将代码分成几部分):
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
}
init()
函数首先创建XMLHttpRequest
对象。 这个请求对象是Ajax的核心。 它以XML格式发送和接收请求。 这段代码检查浏览器是否支持XMLHttpRequest
对象(大多数浏览器都支持它)。 如果使用的是Microsoft Internet Explorer 5.0或更高版本,则执行第二个条件。
req.open("POST", url, true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
一旦代码创建了XMLHttpRequest
对象,就需要设置某些请求属性。 在前面的代码中,第一行设置了请求方法,请求URL和请求的类型(是否异步)。 通过调用XMLHttpRequest
对象上的open()
方法来实现。
在这里,我们将使用POST
方法。 理想情况下,当您需要更改服务器上的状态时,请使用POST
。 我们的应用程序不会更改状态,但是我们仍然更喜欢使用POST
。 url
是要执行的servlet的URL。 true
表示我们将异步处理请求。
对于POST
方法,我们需要设置请求标头Content-Type
。 GET
方法不是必需的。
function validate(formObj) {
init();
req.onreadystatechange = subscriptionValidator;
req.send("subscriptionID=" + formObj.subscriptionID.value);
}
代码演练:回调处理程序1
要继续验证方法,接下来您将subscriptionValidator
回调处理程序分配给onreadystatechange
,它将在请求的每个状态更改时触发。
这个回调处理程序到底是什么? 由于您正在异步处理请求,因此需要一个回调处理程序,当从服务器返回完整响应时将调用该回调处理程序-回调处理程序将在其中验证订阅ID(即,编写实际的验证代码)。
处理程序充当侦听器。 等待直到响应完成。 (有关处理程序代码的更多信息,请参见后面的内容 。)要发送请求,最后一行调用send()
方法。 该请求以“ 名称=值”对的形式发送。 对于GET
方法,该请求将作为URL的一部分send()
,因此send()
方法将传递一个null参数。
该请求被发送到servlet。 Servlet处理请求并实时发送回响应。 这就是servlet处理请求的方式。 下一个代码片段说明了LibraryServlet -- doPost()
方法。
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws
ServletException, IOException {
String ID = null;
ID = req.getParameter("subscriptionID");
if (ID != null) {
String status = "<message>" + this.validID(ID) + "</message>";
this.writeResponse(resp, status);
}
}
代码演练:回调处理程序2
doPost()
方法从请求参数获取subscriptionID
。 为了验证ID,它调用validID()
方法。 这个方法验证ID,并返回true
如果ID是有效的,否则返回false
。 它以XML格式构造返回状态,并通过调用writeResponse()
方法写入响应。 现在检查writeResponse()
方法。
public void writeResponse(HttpServletResponse resp, String output) throws IOException {
resp.setContentType("text/xml");
resp.setHeader("Cache-Control", "no-cache");
resp.getWriter().write(output);
}
响应以XML格式发送。 第一行设置响应内容类型,即text/xml
。 下一行将标头Cache-Control
设置为no-cache
的值。 此标头是必需的。 Ajax要求浏览器不缓存响应输出。 要编写响应,最后一行调用getWriter().write()
方法。
代码演练:回调处理程序3
该请求由Servlet处理,并将响应发送回客户端。 请记住,所有这些都在后台发生,而无需刷新页面。 现在,我们前面讨论过的回调处理程序方法将处理并解析响应:
function subscriptionValidator() {
if (req.readystate == 4) {
if (req.status == 200) {
var messageObj = req.responseXML.getElementsByTagName("message")[0];
var message = messageObj.childNodes[0].nodeValue;
if (message == "true") {
msg.innerHTML = "Subscription is valid";
document.forms[0].order.disabled = false;
} else {
msg.innerHTML = "Subscription not valid";
document.forms[0].order.disabled = true;
}
}
}
}
代码演练:重温XMLHttpRequest
如前所述, XMLHttpRequest
对象是构造和发送请求的核心对象。 它还读取并解析从服务器返回的响应。 看代码部分。
if (req.readystate == 4) {
if (req.status == 200) {
前面的代码检查请求的状态。 如果请求处于就绪状态,则它将读取并解析响应。
就绪状态是什么意思? 当请求对象属性readystate
的值为4
,表示客户端已收到响应并且已完成。 接下来,我们检查请求状态(响应是正常页面还是错误页面)。 为确保响应正常,请检查状态值200
。 如果status
值为200
,则它将处理响应。
var messageObj = req.responseXML.getElementsByTagName("message")[0];
var message = messageObj.childNodes[0].nodeValue;
if (message == "true") {
msg.innerHTML = "Subscription is valid";
document.forms[0].order.disabled = false;
} else {
msg.innerHTML = "Subscription not valid";
document.forms[0].order.disabled = true;
} }
接下来,请求对象通过调用responseXML
属性读取responseXML
。 请注意,该servlet以XML格式返回了响应,因此我们使用responseXML
。 如果发送的响应是文本形式的,则可以使用responseText
属性。
在此示例中,我们处理XML。 servlet在<message>
标签中构造响应。 要解析此XML标记,请在XMLHttpRequest
对象的responseXML
属性上调用getElementsByTagName()
方法。 它获取标签名称和标签的子值。 基于解析的值,响应被格式化并以HTML编写。
您刚刚完成了对订阅ID的验证,所有操作都无需刷新页面。
代码演练:查看作者,发布者,标题
其他功能-View作者 , View发布者和View标题 -沿相似的方向工作。 您必须为每种功能定义单独的处理程序:
function displayList(field) {
init();
titles.innerHTML = " ";
req.onreadystatechange = listHandler;
req.send("select=" + escape(field));
}
function displayTitles(formObj) {
init();
var index = formObj.list.selectedIndex;
var val = formObj.list.options[index].value;
req.onreadystatechange = titlesHandler;
req.send("list=" + val);
}
请记住,此示例应用程序允许用户按作者或发布者查看标题。 因此,将显示“ 作者”列表或“ 发布者”列表 。 在这种情况下,应用程序仅基于用户选择调用一个回调处理程序-换句话说,对于作者和发布者列表,您只有一个listHandler
回调处理程序。
要显示标题列表,您将使用titlesHandler
。 其余功能与servlet处理请求并以XML fornat回写响应一样。 然后,以HTML读取,解析,格式化和编写响应。 您可以将HTML列表呈现为select......options
标签。 此示例代码片段显示了titlesHandler
方法。
var temp = "<select name=\"titles\" multiple\>";
for (var i=0; i<index; i++) {
var listObj = req.responseXML.getElementsByTagName("list")[i];
temp = temp + "<option value=" + i +">" + listObj.childNodes[0].nodeValue
+ "</option>";
}
temp = temp + "</select>";
titles.innerHTML = temp;
到目前为止,我们已经演示了如何实现实时验证和刷新。 通过Ajax,您可以在几种方法中进行选择,以增加Web站点上用户交互的趣味性。 接下来,我们将运行该应用程序。
运行和测试应用程序
运行应用程序
下载示例代码wa-ajax-Library.war并将其复制到Tomcat Webapp目录(例如,c:\ Tomcat 5.0 \ Webapps)。 要启动Tomcat服务器,请输入以下命令:
cd bin
C:\Tomcat 5.0\bin> catalina.bat start
Tomcat现在随部署的Ajax Web应用程序一起启动。
测试应用
要测试该应用程序:
- 打开您的Web浏览器。 指向
http://localhost:tomcatport/Library/order.jsp
,其中变量tompcatport是您的Tomcat服务器运行的端口。您将看到订阅屏幕。
- 在“ 输入订阅ID”字段中,键入除“ John”以外的任何用户ID,然后在该字段之外跳出。
您向服务器异步发出的订阅ID请求将得到验证。 您将看到一条消息“订阅无效”, 如图2所示:
图2.“ Subcription无效”屏幕
该应用程序异步验证用户并提供运行时验证,而无需刷新浏览器。
- 输入用户ID值John 。
您将看到一条消息“订阅有效”。 订阅有效后,应用程序将启用“ 订购”按钮。
- 选择按作者或按发布者单选按钮分别填充作者或发布者下拉列表。
- 从下拉列表中选择作者或发布者。
标题区域是动态填充的( 如图3所示 )。
图3.“ Subcription is valid”屏幕
当您选择作者或发行者时,应用程序将请求服务器在运行时从服务器提供与所选作者或发行者关联的标题信息。 在不刷新浏览器的情况下显示标题信息。
您已经成功安装并测试了此示例Ajax应用程序。
摘要
结论
自成立以来,Ajax已经走了很长一段路。 我们相信Ajax不仅可以应用于设计模式,而且Ajax仍然存在一些问题:
- 浏览器对
XMLHttpRequest
对象的支持可能会受到限制。 大多数浏览器都支持XMLHttpRequest
对象,但是不支持(通常是旧版浏览器)。 - Ajax最适合显示少量数据。 如果要处理大量数据以实时显示列表,则Ajax可能不是正确的解决方案。
- Ajax非常依赖JavaScript。 如果浏览器不支持JavaScript或用户禁用了脚本选项,则根本无法利用Ajax。
- Ajax的异步特性无法保证对多个请求的同步请求处理。 如果您需要确定验证或刷新的优先级,请相应地设计应用程序。
即使有这些潜在的麻烦,Ajax仍然是增强Web页面和解决页面重新加载问题的最佳解决方案。
翻译自: https://www.ibm.com/developerworks/web/tutorials/wa-ajax/index.html