﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-風向逆轉 - 就要爪哇-文章分类-Ajax</title><link>http://www.blogjava.net/iKingQu/category/8713.html</link><description>Java菜鸟升级中...</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 11:26:03 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 11:26:03 GMT</pubDate><ttl>60</ttl><item><title>[收藏]如何使用Ajax技术开发Web应用程序</title><link>http://www.blogjava.net/iKingQu/articles/37336.html</link><dc:creator>風向逆轉 - 就要爪哇</dc:creator><author>風向逆轉 - 就要爪哇</author><pubDate>Sat, 25 Mar 2006 05:28:00 GMT</pubDate><guid>http://www.blogjava.net/iKingQu/articles/37336.html</guid><wfw:comment>http://www.blogjava.net/iKingQu/comments/37336.html</wfw:comment><comments>http://www.blogjava.net/iKingQu/articles/37336.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/iKingQu/comments/commentRss/37336.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iKingQu/services/trackbacks/37336.html</trackback:ping><description><![CDATA[
		<a class="" title="" href="http://www.pconline.com.cn/pcedu/empolder/wz/javascript/0602/755321.html" target="_blank">
				<br />
				<font color="#0000ff">如何使用Ajax技术开发Web应用程序(1)</font>
		</a>
		<font color="#0000ff">
				<br />
		</font>
		<a class="" title="" href="http://www.pconline.com.cn/pcedu/empolder/wz/javascript/0602/755340.html" target="_blank">
				<font color="#0000ff">如何使用Ajax技术开发Web应用程序(2)</font>
		</a>
		<font color="#0000ff">
				<br />
		</font>
		<a class="" title="" href="http://www.pconline.com.cn/pcedu/empolder/wz/javascript/0602/755731.html" target="_blank">
				<font color="#0000ff">如何使用Ajax技术开发Web应用程序(3)</font>
		</a>
		<br />
		<br />
		<br />
<img src ="http://www.blogjava.net/iKingQu/aggbug/37336.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iKingQu/" target="_blank">風向逆轉 - 就要爪哇</a> 2006-03-25 13:28 <a href="http://www.blogjava.net/iKingQu/articles/37336.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[收藏]Ajax应用的详细探讨的技术文章</title><link>http://www.blogjava.net/iKingQu/articles/36535.html</link><dc:creator>風向逆轉 - 就要爪哇</dc:creator><author>風向逆轉 - 就要爪哇</author><pubDate>Mon, 20 Mar 2006 17:40:00 GMT</pubDate><guid>http://www.blogjava.net/iKingQu/articles/36535.html</guid><wfw:comment>http://www.blogjava.net/iKingQu/comments/36535.html</wfw:comment><comments>http://www.blogjava.net/iKingQu/articles/36535.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/iKingQu/comments/commentRss/36535.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iKingQu/services/trackbacks/36535.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<div class="postText">
						<div class="postText">
								<p>
										<font color="#0000ff">
												<strong>AJAX应用的详细探讨</strong>
										</font>
								</p>
								<p>
										<a href="http://blog.csdn.net/Coolingverse/archive/2006/02/22/606164.aspx" target="_blank">
												<font color="#0000ff">AJAX基础教程 </font>
										</a>
								</p>
								<p>
										<a href="http://blog.csdn.net/baggio785/archive/2006/01/14/578891.aspx" id="CategoryEntryList.ascx_EntryStoryList_Entries__ctl9_TitleUrl" target="_blank">
												<font color="#0000ff">AJAX开发简略 (一) </font>
										</a>
								</p>
								<p>
										<a href="http://blog.csdn.net/baggio785/archive/2006/01/14/578898.aspx" id="CategoryEntryList.ascx_EntryStoryList_Entries__ctl8_TitleUrl" target="_blank">
												<font color="#0000ff">AJAX开发简略 (二) <br /></font>
										</a>
										<br />
										<a class="" href="http://www-128.ibm.com/developerworks/cn/xml/wa-ajaxintro1.html" target="_blank" title="">
												<font color="#0000ff">掌握 Ajax，第 1 部分: Ajax 简介<br /></font>
										</a>
										<br />
										<a class="" href="http://www-128.ibm.com/developerworks/cn/xml/wa-ajaxintro2/" target="_blank" title="">
												<font color="#0000ff">掌握 Ajax，第 2 部分: 使用 JavaScript 和 Ajax 发出异步请求</font>
										</a>
										<br />
										<br />
										<a class="" href="http://www-128.ibm.com/developerworks/cn/xml/wa-ajaxintro3/" target="_blank" title="">
												<font color="#0000ff">掌握 Ajax，第 3 部分: Ajax 中的高级请求和响应</font>
										</a> <br /><br /><a class="" href="http://blog.csdn.net/baggio785/archive/2006/02/15/599373.aspx" target="_blank" title=""><font color="#0000ff">用AJAX来控制书签和回退按钮</font></a></p>
								<p>
										<a href="http://blog.csdn.net/baggio785/archive/2006/01/16/580583.aspx" id="CategoryEntryList.ascx_EntryStoryList_Entries__ctl6_TitleUrl" target="_blank">
												<font color="#0000ff">面向 Java 开发人员的 Ajax: 结合 Direct Web Remoting 使用 Ajax</font>
												<font color="#000080">
												</font>
										</a>
								</p>
								<p>
										<a href="http://blog.csdn.net/baggio785/archive/2005/12/23/560591.aspx" id="CategoryEntryList.ascx_EntryStoryList_Entries__ctl2_TitleUrl" target="_blank">
												<font color="#0000ff">WEB2.0中AJAX应用的详细探讨</font>
												<font color="#000080">
												</font>
										</a>
								</p>
								<p>
										<a href="http://blog.csdn.net/baggio785/archive/2006/02/14/598558.aspx" id="CategoryEntryList.ascx_EntryStoryList_Entries__ctl3_TitleUrl" target="_blank">
												<font color="#0000ff">AJAX：开发者新的技术天地介绍</font>
												<font color="#000080">
												</font>
										</a>
								</p>
								<p>
										<a href="http://blog.csdn.net/baggio785/archive/2006/01/19/583805.aspx" id="CategoryEntryList.ascx_EntryStoryList_Entries__ctl5_TitleUrl" target="_blank">
												<font color="#0000ff">Ajax In Action 书籍下载</font>
												<font color="#000080">
												</font>
										</a>
										<br />
										<br />
										<font color="#0000ff">掌握Ajax系列：<a href="http://www-128.ibm.com/developerworks/cn/views/xml/articles.jsp">http://www-128.ibm.com/developerworks/cn/views/xml/articles.jsp</a></font>
								</p>
						</div>
				</div>
		</div>
<img src ="http://www.blogjava.net/iKingQu/aggbug/36535.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iKingQu/" target="_blank">風向逆轉 - 就要爪哇</a> 2006-03-21 01:40 <a href="http://www.blogjava.net/iKingQu/articles/36535.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[收藏]AJAX开发简略 (二)</title><link>http://www.blogjava.net/iKingQu/articles/36524.html</link><dc:creator>風向逆轉 - 就要爪哇</dc:creator><author>風向逆轉 - 就要爪哇</author><pubDate>Mon, 20 Mar 2006 16:41:00 GMT</pubDate><guid>http://www.blogjava.net/iKingQu/articles/36524.html</guid><wfw:comment>http://www.blogjava.net/iKingQu/comments/36524.html</wfw:comment><comments>http://www.blogjava.net/iKingQu/articles/36524.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/iKingQu/comments/commentRss/36524.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iKingQu/services/trackbacks/36524.html</trackback:ping><description><![CDATA[
		<p>
				<a>
						<strong>七、AJAX开发</strong>
				</a>
				<br />　　到这里，已经可以清楚的知道AJAX是什么，AJAX能做什么，AJAX什么地方不好。如果你觉得AJAX真的能给你的开发工作带来改进的话，那么继续看看怎么使用AJAX吧。<a name="a71"></a></p>
		<strong>
				<a>7.1</a>、AJAX应用到的技术</strong>
		<br />　　AJAX涉及到的7项技术中，个人认为Javascript、XMLHttpRequest、DOM、XML比较有用。<br /><br /><a>A</a>、XMLHttpRequest对象<br />　　XMLHttpRequest是XMLHTTP组件的对象，通过这个对象，AJAX可以像桌面应用程序一样只同服务器进行数据层面的交换，而不用每次都刷新界面，也不用每次将数据处理的工作都交给服务器来做；这样既减轻了服务器负担又加快了响应速度、缩短了用户等待的时间。 
<p>　　IE5.0开始，开发人员可以在Web页面内部使用XMLHTTP ActiveX组件扩展自身的功能，不用从当前的Web页面导航就可以直接传输数据到服务器或者从服务器接收数据。,Mozilla1.0以及NetScape7则是创建继承XML的代理类XMLHttpRequest；对于大多数情况，XMLHttpRequest对象和XMLHTTP组件很相似，方法和属性类似，只是部分属性不同。</p><pre class="precode">XMLHttpRequest对象初始化：
&lt;script language=”javascript”&gt;
var http_request = false;
//IE浏览器
http_request = new ActiveXObject("Msxml2.XMLHTTP");
http_request = new ActiveXObject("Microsoft.XMLHTTP");
//Mozilla浏览器
http_request = new XMLHttpRequest();
&lt;/script&gt;</pre><p>　　XMLHttpRequest对象的方法：</p><table cellspacing="1" cellpadding="4" bgcolor="#000000"><tbody><tr bgcolor="#ffffff"><td valign="top" width="489">方法</td><td valign="top" width="221">描述</td></tr><tr bgcolor="#ffffff"><td valign="top" width="489">abort()</td><td valign="top" width="221"><p>停止当前请求</p></td></tr><tr bgcolor="#ffffff"><td valign="top" width="489">getAllResponseHeaders()</td><td valign="top" width="221"><p>作为字符串返回完整的headers</p></td></tr><tr bgcolor="#ffffff"><td valign="top" width="489">getResponseHeader("headerLabel")</td><td valign="top" width="221"><p>作为字符串返回单个的header标签</p></td></tr><tr bgcolor="#ffffff"><td valign="top" width="489">open("method","URL"[,asyncFlag[,"userName"[, "password"]]])</td><td valign="top" width="221">设置未决的请求的目标 URL，方法，和其他参数</td></tr><tr bgcolor="#ffffff"><td valign="top" width="489">send(content)</td><td valign="top" width="221">发送请求</td></tr><tr bgcolor="#ffffff"><td valign="top" width="489">setRequestHeader("label", "value")</td><td valign="top" width="221">设置header并和请求一起发送</td></tr></tbody></table><p>　　XMLHttpRequest对象的属性：</p><table cellspacing="1" cellpadding="4" bgcolor="#000000"><tbody><tr bgcolor="#ffffff"><td valign="top" width="159">属性</td><td valign="top" width="551">描述</td></tr><tr bgcolor="#ffffff"><td valign="top" width="159">onreadystatechange</td><td valign="top" width="551">状态改变的事件触发器</td></tr><tr bgcolor="#ffffff"><td valign="top" width="159">readyState</td><td valign="top" width="551">对象状态(integer): 
<p> </p><br />0 = 未初始化 <br />1 = 读取中<br />2 = 已读取<br />3 = 交互中<br />4 = 完成</td></tr><tr bgcolor="#ffffff"><td valign="top" width="159">responseText</td><td valign="top" width="551">服务器进程返回数据的文本版本</td></tr><tr bgcolor="#ffffff"><td valign="top" width="159">responseXML</td><td valign="top" width="551">服务器进程返回数据的兼容DOM的XML文档对象</td></tr><tr bgcolor="#ffffff"><td valign="top" width="159">status</td><td valign="top" width="551">服务器返回的状态码, 如：404 = "文件未找到" 、200 ="成功"</td></tr><tr bgcolor="#ffffff"><td valign="top" width="159">statusText</td><td valign="top" width="551">服务器返回的状态文本信息</td></tr></tbody></table><a><br />B</a>、Javascript<br />　　 Javascript一直被定位为客户端的脚本语言，应用最多的地方是表单数据的校验。现在，可以通过Javascript操作XMLHttpRequest，来跟数据库打交道。<a><br /><br />C</a>、DOM<br />　　 DOM（Document Object Model）是提供给HTML和XML使用的一组API，提供了文件的表述结构，并可以利用它改变其中的内容和可见物。脚本语言通过DOM才可以跟页面进行交互。Web开发人员可操作及建立文件的属性、方法以及事件都以对象来展现。比如，document就代表页面对象本身。<br /><br /><a>D</a>、XML<br />　　通过XML（Extensible Markup Language），可以规范的定义结构化数据，是网上传输的数据和文档符合统一的标准。用XML表述的数据和文档，可以很容易的让所有程序共享。<a name="a72"></a><br /><br /><strong><a>7.2</a>、AJAX开发框架</strong><br />　　这里，我们通过一步步的解析，来形成一个发送和接收XMLHttpRequest请求的程序框架。AJAX实质上也是遵循Request/Server模式，所以这个框架基本的流程也是：对象初始化à发送请求à服务器接收à服务器返回à客户端接收à修改客户端页面内容。只不过这个过程是异步的。<br /><br /><a>A</a>、初始化对象并发出XMLHttpRequest请求<br />　　为了让Javascript可以向服务器发送HTTP请求，必须使用XMLHttpRequest对象。使用之前，要先将XMLHttpRequest对象实例化。之前说过，各个浏览器对这个实例化过程实现不同。IE以ActiveX控件的形式提供，而Mozilla等浏览器则直接以XMLHttpRequest类的形式提供。为了让编写的程序能够跨浏览器运行，要这样写： <pre class="precode">if (window.XMLHttpRequest) { // Mozilla, Safari, ...
       http_request = new XMLHttpRequest();
  } 
  else if (window.ActiveXObject) { // IE
       http_request = new ActiveXObject("Microsoft.XMLHTTP");
}</pre><p>　　有些版本的Mozilla浏览器处理服务器返回的未包含XML mime-type头部信息的内容时会出错。因此，要确保返回的内容包含text/xml信息。 </p><pre class="precode">http_request = new XMLHttpRequest();
http_request.overrideMimeType('text/xml');</pre>B、指定响应处理函数<br />　　接下来要指定当服务器返回信息时客户端的处理方式。只要将相应的处理函数名称赋给XMLHttpRequest对象的onreadystatechange属性就可以了。比如： 
<p> </p><pre class="precode">http_request.onreadystatechange = processRequest;</pre><p>　　需要指出的时，这个函数名称不加括号，不指定参数。也可以用Javascript即时定义函数的方式定义响应函数。比如：</p><p class="precode">http_request.onreadystatechange = function() { };</p><pre> </pre><a>C</a>、发出HTTP请求 
<p>　　指定响应处理函数之后，就可以向服务器发出HTTP请求了。这一步调用XMLHttpRequest对象的open和send方法。</p><pre class="precode">http_request.open('GET', 'http://www.example.org/some.file', true);
http_request.send(null);</pre><p>　　open的第一个参数是HTTP请求的方法，为Get、Post或者Head。</p><p>　　open的第二个参数是目标URL。基于安全考虑，这个URL只能是同网域的，否则会提示“没有权限”的错误。这个URL可以是任何的URL，包括需要服务器解释执行的页面，不仅仅是静态页面。目标URL处理请求XMLHttpRequest请求则跟处理普通的HTTP请求一样，比如JSP可以用request.getParameter(“”)或者request.getAttribute(“”)来取得URL参数值。</p><p>　　open的第三个参数只是指定在等待服务器返回信息的时间内是否继续执行下面的代码。如果为True，则不会继续执行，直到服务器返回信息。默认为True。</p><p>　　按照顺序，open调用完毕之后要调用send方法。send的参数如果是以Post方式发出的话，可以是任何想传给服务器的内容。不过，跟form一样，如果要传文件或者Post内容给服务器，必须先调用setRequestHeader方法，修改MIME类别。如下：</p><pre class="precode">http_request.setRequestHeader(“Content-Type”,”application/x-www-form-urlencoded”);</pre><p>　　这时资料则以查询字符串的形式列出，作为sned的参数，例如：</p><pre class="precode">name=value&amp;anothername=othervalue&amp;so=on</pre>D、处理服务器返回的信息 <br />　　在第二步我们已经指定了响应处理函数，这一步，来看看这个响应处理函数都应该做什么。 
<p>　　首先，它要检查XMLHttpRequest对象的readyState值，判断请求目前的状态。参照前文的属性表可以知道，readyState值为4的时候，代表服务器已经传回所有的信息，可以开始处理信息并更新页面内容了。如下：</p><pre class="precode">if (http_request.readyState == 4) {
    // 信息已经返回，可以开始处理
} else {
    // 信息还没有返回，等待
}</pre><p>　　服务器返回信息后，还需要判断返回的HTTP状态码，确定返回的页面没有错误。所有的状态码都可以在<a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"><font color="#002c99">W3C</font></a>的官方网站上查到。其中，200代表页面正常。</p><pre class="precode">if (http_request.status == 200) {
    // 页面正常，可以开始处理信息
} else {
    // 页面有问题
}
</pre><p>　　XMLHttpRequest对成功返回的信息有两种处理方式：<br />　　 responseText：将传回的信息当字符串使用；<br />　　 responseXML：将传回的信息当XML文档使用，可以用DOM处理。</p><a>E</a>、一个初步的开发框架<br />　　总结上面的步骤，我们整理出一个初步的可用的开发框架，供以后调用；这里，将服务器返回的信息用window.alert以字符串的形式显示出来： <pre class="precode">&lt;script language="javascript"&gt;
	var http_request = false;
	function send_request(url) {//初始化、指定处理函数、发送请求的函数
		http_request = false;
		//开始初始化XMLHttpRequest对象
		if(window.XMLHttpRequest) { //Mozilla 浏览器
			http_request = new XMLHttpRequest();
			if (http_request.overrideMimeType) {//设置MiME类别
				http_request.overrideMimeType("text/xml");
			}
		}
		else if (window.ActiveXObject) { // IE浏览器
			try {
				http_request = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
				try {
					http_request = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (e) {}
			}
		}
		if (!http_request) { // 异常，创建对象实例失败
			window.alert("不能创建XMLHttpRequest对象实例.");
			return false;
		}
		http_request.onreadystatechange = processRequest;
		// 确定发送请求的方式和URL以及是否同步执行下段代码
		http_request.open("GET", url, true);
		http_request.send(null);
	}
	// 处理返回信息的函数
    function processRequest() {
        if (http_request.readyState == 4) { // 判断对象状态
            if (http_request.status == 200) { // 信息已经成功返回，开始处理信息
                alert(http_request.responseText);
            } else { //页面不正常
                alert("您所请求的页面有异常。");
            }
        }
    }
&lt;/script&gt;<a name="a73"></a></pre><strong>7.3、简单的示例</strong><br />　　接下来，我们利用上面的开发框架来做两个简单的应用。<br /><br /><a>A</a>、数据校验<br />　　在用户注册的表单中，经常碰到要检验待注册的用户名是否唯一。传统的做法是采用window.open的弹出窗口，或者window. showModalDialog的对话框。不过，这两个都需要打开窗口。采用AJAX后，采用异步方式直接将参数提交到服务器，用window.alert将服务器返回的校验信息显示出来。代码如下： 
<p>　　在&lt;body&gt;&lt;/body&gt;之间增加一段form表单代码：</p><pre class="precode">&lt;form name="form1" action="" method="post"&gt;<br />
  用户名：&lt;input type="text" name="username" value=""&gt;&amp;nbsp;<br />
  &lt;input type="button" name="check" value="唯一性检查" onClick="userCheck()"&gt;<br />
  &lt;input type="submit" name="submit" value="提交"&gt;<br />
&lt;/form&gt;</pre><p>　　在开发框架的基础上再增加一个调用函数：</p><pre class="precode">function userCheck() {
	var f = document.form1;
	var username = f.username.value;
	if(username=="") {
		window.alert("用户名不能为空。");
		f.username.focus();
		return false;
	}
	else {
		send_request('sample1_2.jsp?username='+username);
	}
}
</pre><p>　　看看sample1_2.jsp做了什么：</p><pre class="precode">&lt;%@ page contentType="text/html; charset=gb2312" errorPage="" %&gt;
&lt;%
String username = request.getParameter("username");
if("educhina".equals(username)) out.print("用户名已经被注册，请更换一个用户名。");
else out.print("用户名尚未被使用，您可以继续。");
%&gt;</pre><p>　　运行一下，嗯，没有弹出窗口，没有页面刷新，跟预想的效果一样。如果需要的话，可以在sample1_2.jsp中实现更复杂的功能。最后，只要将反馈信息打印出来就可以了。</p><p align="center"><img alt="" src="http://dev2dev.bea.com.cn/images/image051114016.jpg" /><br /><img alt="" src="http://dev2dev.bea.com.cn/images/image051114018.jpg" /></p><a>B</a>、级联菜单<br />　　我们在第五部分提到利用AJAX改进级联菜单的设计。接下来，我们就演示一下如何“按需取数据”。 
<p>　　首先，在&lt;body&gt;&lt;/body&gt;中间增加如下HTML代码：</p><pre class="precode">&lt;table width="200" border="0" cellspacing="0" cellpadding="0"&gt;
    &lt;tr&gt;
        &lt;td height="20"&gt;
			&lt;a href="javascript:void(0)" onClick="showRoles('pos_1')"&gt;经理室&lt;/a&gt;
		&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr style="display:none"&gt;
        &lt;td height="20" id="pos_1"&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td height="20"&gt;
			&lt;a href="javascript:void(0)" onClick="showRoles('pos_2')"&gt;开发部&lt;/a&gt;
		&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr style="display:none "&gt;
        &lt;td id="pos_2" height="20"&gt; &lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;
</pre><p>　　在框架的基础上增加一个响应函数showRoles(obj)：</p><pre class="precode">//显示部门下的岗位
function showRoles(obj) {
	document.getElementById(obj).parentNode.style.display = "";
	document.getElementById(obj).innerHTML = "正在读取数据..."
	currentPos = obj;
	send_request("sample2_2.jsp?playPos="+obj);
}
</pre><p>　　修改框架的processRequest函数：</p><pre class="precode">// 处理返回信息的函数
function processRequest() {
  if (http_request.readyState == 4) { // 判断对象状态
    if (http_request.status == 200) { // 信息已经成功返回，开始处理信息
	document.getElementById(currentPos).innerHTML = http_request.responseText;
    } else { //页面不正常
      alert("您所请求的页面有异常。");
    }
  }
}
</pre><p>　　最后就是smaple2_2.jsp了：</p><pre class="precode">&lt;%@ page contentType="text/html; charset=gb2312" errorPage="" %&gt;<br />&lt;%<br />String playPos = request.getParameter("playPos");
if("pos_1".equals(playPos)) 
   out.print("&amp;nbsp;&amp;nbsp;总经理&lt;br&gt;&amp;nbsp;&amp;nbsp;副总经理");
else if("pos_2".equals(playPos)) 
   out.println("&amp;nbsp;&amp;nbsp;总工程师&lt;br&gt;&amp;nbsp;&amp;nbsp;软件工程师");<br />%&gt;
</pre><p>　　运行一下看看效果：</p><p align="center"><img alt="" src="http://dev2dev.bea.com.cn/images/image051114024.jpg" /><img alt="" src="http://dev2dev.bea.com.cn/images/image051114026.jpg" /><a name="a74"></a></p><strong><a>7.4</a>、文档对象模型（DOM）</strong><br />　　文档对象模型（DOM）是表示文档（比如HTML和XML）和访问、操作构成文档的各种元素的应用程序接口（API）。一般的，支持Javascript的所有浏览器都支持DOM。本文所涉及的DOM，是指W3C定义的标准的文档对象模型，它以树形结构表示HTML和XML文档，定义了遍历这个树和检查、修改树的节点的方法和属性。<br /><br />7.4.1、DOM眼中的HTML文档：树<br />　　在DOM眼中，HTML跟XML一样是一种树形结构的文档，&lt;html&gt;是根（root）节点，&lt;head&gt;、&lt;title&gt;、&lt;body&gt;是&lt;html&gt;的子（children）节点，互相之间是兄弟（sibling）节点；&lt;body&gt;下面才是子节点&lt;table&gt;、&lt;span&gt;、&lt;p&gt;等等。如下图： 
<p>　　<img alt="" src="http://dev2dev.bea.com.cn/images/image051114027.gif" /></p><p>　　这个是不是跟XML的结构有点相似呢。不同的是，HTML文档的树形主要包含表示元素、标记的节点和表示文本串的节点。</p>7.4.2、HTML文档的节点<br />　　DOM下，HTML文档各个节点被视为各种类型的Node对象。每个Node对象都有自己的属性和方法，利用这些属性和方法可以遍历整个文档树。由于HTML文档的复杂性，DOM定义了nodeType来表示节点的类型。这里列出Node常用的几种节点类型： 
<table cellspacing="1" cellpadding="4" bgcolor="#000000"><tbody><tr bgcolor="#ffffff"><td valign="top" width="159">接口</td><td valign="top" width="322">nodeType常量</td><td valign="top" width="113">nodeType值</td><td valign="top" width="117">备注</td></tr><tr bgcolor="#ffffff"><td valign="top" width="159">Element</td><td valign="top" width="322">Node.ELEMENT_NODE</td><td valign="top" width="113">1</td><td valign="top" width="117">元素节点</td></tr><tr bgcolor="#ffffff"><td valign="top" width="159">Text</td><td valign="top" width="322">Node.TEXT_NODE</td><td valign="top" width="113">3</td><td valign="top" width="117">文本节点</td></tr><tr bgcolor="#ffffff"><td valign="top" width="159">Document</td><td valign="top" width="322">Node.DOCUMENT_NODE</td><td valign="top" width="113">9</td><td valign="top" width="117">document</td></tr><tr bgcolor="#ffffff"><td valign="top" width="159">Comment</td><td valign="top" width="322">Node.COMMENT_NODE</td><td valign="top" width="113">8</td><td valign="top" width="117">注释的文本</td></tr><tr bgcolor="#ffffff"><td valign="top" width="159">DocumentFragment</td><td valign="top" width="322">Node.DOCUMENT_FRAGMENT_NODE</td><td valign="top" width="113">11</td><td valign="top" width="117">document片断</td></tr><tr bgcolor="#ffffff"><td valign="top" width="159">Attr</td><td valign="top" width="322">Node.ATTRIBUTE_NODE</td><td valign="top" width="113">2</td><td valign="top" width="117">节点属性</td></tr></tbody></table><p>　　DOM树的根节点是个Document对象，该对象的documentElement属性引用表示文档根元素的Element对象（对于HTML文档，这个就是&lt;html&gt;标记）。Javascript操作HTML文档的时候，document即指向整个文档，&lt;body&gt;、&lt;table&gt;等节点类型即为Element。Comment类型的节点则是指文档的注释。具体节点类型的含义，请参考《Javascript权威指南》，在此不赘述。</p><p>　　Document定义的方法大多数是生产型方法，主要用于创建可以插入文档中的各种类型的节点。常用的Document方法有：</p><table cellspacing="1" cellpadding="4" bgcolor="#000000"><tbody><tr bgcolor="#ffffff"><td valign="top" width="204">方法</td><td valign="top" width="506">描述</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">createAttribute()</td><td valign="top" width="506">用指定的名字创建新的Attr节点。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">createComment()</td><td valign="top" width="506">用指定的字符串创建新的Comment节点。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">createElement()</td><td valign="top" width="506">用指定的标记名创建新的Element节点。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">createTextNode()</td><td valign="top" width="506">用指定的文本创建新的TextNode节点。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">getElementById()</td><td valign="top" width="506">返回文档中具有指定id属性的Element节点。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">getElementsByTagName()</td><td valign="top" width="506">返回文档中具有指定标记名的所有Element节点。</td></tr></tbody></table><p>　　对于Element节点，可以通过调用getAttribute()、setAttribute()、removeAttribute()方法来查询、设置或者删除一个Element节点的性质，比如&lt;table&gt;标记的border属性。下面列出Element常用的属性：</p><table cellspacing="1" cellpadding="4" bgcolor="#000000"><tbody><tr bgcolor="#ffffff"><td valign="top" width="99">属性</td><td valign="top" width="611">描述</td></tr><tr bgcolor="#ffffff"><td valign="top" width="99">tagName</td><td valign="top" width="611">元素的标记名称，比如&lt;p&gt;元素为P。HTML文档返回的tabName均为大写。</td></tr></tbody></table><p>　　Element常用的方法：</p><table cellspacing="1" cellpadding="4" bgcolor="#000000"><tbody><tr bgcolor="#ffffff"><td valign="top" width="204">方法</td><td valign="top" width="506">描述</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">getAttribute()</td><td valign="top" width="506">以字符串形式返回指定属性的值。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">getAttributeNode()</td><td valign="top" width="506">以Attr节点的形式返回指定属性的值。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">getElementsByTabName()</td><td valign="top" width="506">返回一个Node数组，包含具有指定标记名的所有Element节点的子孙节点，其顺序为在文档中出现的顺序。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">hasAttribute()</td><td valign="top" width="506">如果该元素具有指定名字的属性，则返回true。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">removeAttribute()</td><td valign="top" width="506">从元素中删除指定的属性。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">removeAttributeNode()</td><td valign="top" width="506">从元素的属性列表中删除指定的Attr节点。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">setAttribute()</td><td valign="top" width="506">把指定的属性设置为指定的字符串值，如果该属性不存在则添加一个新属性。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="204">setAttributeNode()</td><td valign="top" width="506">把指定的Attr节点添加到该元素的属性列表中。</td></tr></tbody></table><p>　　Attr对象代表文档元素的属性，有name、value等属性，可以通过Node接口的attributes属性或者调用Element接口的getAttributeNode()方法来获取。不过，在大多数情况下，使用Element元素属性的最简单方法是getAttribute()和setAttribute()两个方法，而不是Attr对象。 </p>7.4.3、使用DOM操作HTML文档<br />　　Node对象定义了一系列属性和方法，来方便遍历整个文档。用parentNode属性和childNodes[]数组可以在文档树中上下移动；通过遍历childNodes[]数组或者使用firstChild和nextSibling属性进行循环操作，也可以使用lastChild和previousSibling进行逆向循环操作，也可以枚举指定节点的子节点。而调用appendChild()、insertBefore()、removeChild()、replaceChild()方法可以改变一个节点的子节点从而改变文档树。 
<p>　　需要指出的是，childNodes[]的值实际上是一个NodeList对象。因此，可以通过遍历childNodes[]数组的每个元素，来枚举一个给定节点的所有子节点；通过递归，可以枚举树中的所有节点。下表列出了Node对象的一些常用属性和方法：</p><p>　　Node对象常用属性：</p><table cellspacing="1" cellpadding="4" bgcolor="#000000"><tbody><tr bgcolor="#ffffff"><td valign="top" width="114">属性</td><td valign="top" width="596">描述</td></tr><tr bgcolor="#ffffff"><td valign="top" width="114">attributes</td><td valign="top" width="596">如果该节点是一个Element，则以NamedNodeMap形式返回该元素的属性。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="114">childNodes</td><td valign="top" width="596">以Node[]的形式存放当前节点的子节点。如果没有子节点，则返回空数组。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="114">firstChild</td><td valign="top" width="596">以Node的形式返回当前节点的第一个子节点。如果没有子节点，则为null。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="114">lastChild</td><td valign="top" width="596">以Node的形式返回当前节点的最后一个子节点。如果没有子节点，则为null。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="114">nextSibling</td><td valign="top" width="596">以Node的形式返回当前节点的兄弟下一个节点。如果没有这样的节点，则返回null。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="114">nodeName</td><td valign="top" width="596">节点的名字，Element节点则代表Element的标记名称。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="114">nodeType</td><td valign="top" width="596">代表节点的类型。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="114">parentNode</td><td valign="top" width="596">以Node的形式返回当前节点的父节点。如果没有父节点，则为null。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="114">previousSibling</td><td valign="top" width="596">以Node的形式返回紧挨当前节点、位于它之前的兄弟节点。如果没有这样的节点，则返回null。</td></tr></tbody></table><p>　　Node对象常用方法：</p><table cellspacing="1" cellpadding="4" bgcolor="#000000"><tbody><tr bgcolor="#ffffff"><td valign="top" width="144">方法</td><td valign="top" width="566">描述</td></tr><tr bgcolor="#ffffff"><td valign="top" width="144">appendChild()</td><td valign="top" width="566">通过把一个节点增加到当前节点的childNodes[]组，给文档树增加节点。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="144">cloneNode()</td><td valign="top" width="566">复制当前节点，或者复制当前节点以及它的所有子孙节点。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="144">hasChildNodes()</td><td valign="top" width="566">如果当前节点拥有子节点，则将返回true。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="144">insertBefore()</td><td valign="top" width="566">给文档树插入一个节点，位置在当前节点的指定子节点之前。如果该节点已经存在，则删除之再插入到它的位置。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="144">removeChild()</td><td valign="top" width="566">从文档树中删除并返回指定的子节点。</td></tr><tr bgcolor="#ffffff"><td valign="top" width="144">replaceChild()</td><td valign="top" width="566">从文档树中删除并返回指定的子节点，用另一个节点替换它。</td></tr></tbody></table><p>　　接下来，让我们使用上述的DOM应用编程接口，来试着操作HTML文档。</p><p>　　<strong>A、遍历文档的节点</strong></p><p>　　DOM把一个HTML文档视为树，因此，遍历整个树是应该是家常便饭。跟之前说过的一样，这里我们提供两个遍历树的例子。通过它，我们能够学会如何使用childNodes[]和firstChile、lastChild、nextSibling、previousSibling遍历整棵树。</p><p>　　<strong>例子1-- sample3_1.htm：<br /></strong>　　这个例子使用了childNodes[]和递归方式来遍历整个文档，统计文档中出现的Element元素总数，并把Element标记名全部打印出来。需要特别注意的是，在使用DOM时，必须等文档被装载完毕再执行遍历等行为操作文档。sample3_1.htm具体代码如下：</p><pre class="precode">&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;
&lt;title&gt;无标题文档&lt;/title&gt;
&lt;script language="javascript"&gt;
var elementName = ""; //全局变量，保存Element标记名，使用完毕要清空
function countTotalElement(node) { //参数node是一个Node对象
	var total = 0;
	if(node.nodeType == 1) { //检查node是否为Element对象
		total++;			//如果是，计数器加1
		elementName = elementName + node.tagName + "\r\n"; //保存标记名
	}
	var childrens = node.childNodes;		//获取node的全部子节点
	for(var i=0;i&lt;childrens.length;i++) {
		total += countTotalElement(childrens[i]); //在每个子节点上进行递归操作
	}
	return total;
}
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;a href="javascript:void(0)" 
onClick="alert('标记总数：' + countTotalElement(document) + '\r\n<br /><br />全部标记如下：\r\n' + elementName);elementName='';"&gt;开始统计&lt;/a&gt;
&lt;/body&gt;
&lt;/html&gt;</pre><p align="center"><img alt="" src="http://dev2dev.bea.com.cn/images/image0511140032.jpg" /><img alt="" src="http://dev2dev.bea.com.cn/images/image0511140042.jpg" /></p><p>　　<strong>例子2 – sample3_2.htm：<br /></strong>　　接下来使用firstChile、lastChild、nextSibling、previousSibling遍历整个文档树。修改一下countTotalElement函数，其他跟sample3_1.htm一样：</p><pre class="precode">function countTotalElement(node) { //参数node是一个Node对象
	var total = 0;
	if(node.nodeType == 1) { //检查node是否为Element对象
		total++;			//如果是，计数器加1
		elementName = elementName + node.tagName + "\r\n"; //保存标记名
	}
	var childrens = node.childNodes;		//获取node的全部子节点
	for(var m=node.firstChild; m!=null;m=m.nextSibling) {
		total += countTotalElement(m); //在每个子节点上进行递归操作
	}
	return total;
}
</pre><p>　　<strong>B、搜索文档中特定的元素<br /></strong>　　在使用DOM的过程中，有时候需要定位到文档中的某个特定节点，或者具有特定类型的节点列表。这种情况下，可以调用Document对象的getElementsByTagName()和getElementById()方法来实现。</p><p>　　document.getElementsByTagName()返回文档中具有指定标记名的全部Element节点数组（也是NodeList类型）。Element出现在数组中的顺序就是他们在文档中出现的顺序。传递给getElementsByTagName()的参数忽略大小写。比如，想定位到第一个&lt;table&gt;标记，可以这样写：document.getElementsByTagName(“table”)[0]。例外的，可以使用document.body定位到&lt;body&gt;标记，因为它是唯一的。</p><p>　　getElementsByTagName()返回的数组取决于文档。一旦文档改变，返回结果也立即改变。相比，getElementById()则比较灵活，可以随时定位到目标，只是要实现给目标元素一个唯一的id属性值。这个我们在《AJAX开发简略》的“级联菜单”例子中已经使用过了。</p><p>　　Element对象也支持getElementsByTagName()和getElementById()。不同的是，搜索领域只针对调用者的子节点。</p><p>　　<strong>C、修改文档内容<br /></strong>　　遍历整棵文档树、搜索特定的节点，我们最终目的之一是要修改文档内容。接下来的三个例子将使用Node的几个常用方法，来演示如何修改文档内容。</p><p>　　<strong>例子3 -- sample4_1.htm：<br /></strong>　　这个例子包含三个文本节点和一个按钮。点击按钮后，三个文本节点和按钮的顺序将被颠倒。程序使用了Node的appendChild()和removeChild()方法。</p><pre class="precode">&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;
&lt;title&gt;无标题文档&lt;/title&gt;
&lt;script language="javascript"&gt;
	function reverseNode(node) { // 颠倒节点node的顺序
		var kids = node.childNodes; //获取子节点列表
		var kidsNum = kids.length; //统计子节点总数
		for(var i=kidsNum-1;i&gt;=0;i--) { //逆向遍历子节点列表
			var c = node.removeChild(kids[i]); //删除指定子节点，保存在c中
			node.appendChild(c); //将c放在新位置上
		}
	}
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;第一行&lt;/p&gt;
&lt;p&gt;第二行&lt;/p&gt;
&lt;p&gt;第三行&lt;/p&gt;
&lt;p&gt;&lt;input type="button" name="reverseGo" value="颠倒" 
onClick="reverseNode(document.body)"&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre><p align="center"><img alt="" src="http://dev2dev.bea.com.cn/images/image051114007.jpg" /><img alt="" src="http://dev2dev.bea.com.cn/images/image051114008.jpg" /></p><p>　　<strong>例子4-- sample4_2.htm：<br /></strong>　　例子1通过直接操作body的子节点来修改文档。在HTML文档中，布局和定位常常通过表格&lt;table&gt;来实现。因此，例子4将演示操作表格内容，将表格的四个单元行顺序颠倒。如果没有使用&lt;tbody&gt;标签，则&lt;table&gt;把全部的&lt;tr&gt;当做是属于一个子节点&lt;tbody&gt;，所以我们采用数组缓存的方式，把行数据颠倒一下。这个例子同时也演示了如何使用DOM创建表格单元行。</p><pre class="precode">&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;
&lt;title&gt;无标题文档&lt;/title&gt;
&lt;script language="javascript"&gt;
function reverseTable() {
	var node = document.getElementsByTagName("table")[0]; //第一个表格
	var child = node.getElementsByTagName("tr"); //取得表格内的所有行
	var newChild = new Array(); //定义缓存数组，保存行内容
	for(var i=0;i&lt;child.length;i++) {
		newChild[i] = child[i].firstChild.innerHTML; 
	}
	node.removeChild(node.childNodes[0]); //删除全部单元行
	var header = node.createTHead(); //新建表格行头
	for(var i=0;i&lt;newChild.length;i++) {
		var headerrow = header.insertRow(i); //插入一个单元行
		var cell = headerrow.insertCell(0); //在单元行中插入一个单元格
		//在单元格中创建TextNode节点
		cell.appendChild(document.createTextNode(newChild[newChild.length-i-1]));
	}
}
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;table width="200" border="1" cellpadding="4" cellspacing="0"&gt;
    &lt;tr&gt;
        &lt;td height="25"&gt;第一行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td height="25"&gt;第二行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td height="25"&gt;第三行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td height="25"&gt;第四行&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;input type="button" name="reverse" value="开始颠倒" onClick="reverseTable()"&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre><p align="center"><img alt="" src="http://dev2dev.bea.com.cn/images/image051114011.jpg" /><img alt="" src="http://dev2dev.bea.com.cn/images/image051114012.jpg" /></p><p>　　<strong>例子5 -- sample4_3.htm：<br /></strong>　　正如我们在Node节点介绍部分所指出的那样，appendChild()、replaceChild()、removeChild()、insertBefore()方法会立即改变文档的结构。下面的例子包含两个表格，我们试着把表格二的内容替换表格一的内容。</p><pre class="precode">&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;
&lt;title&gt;无标题文档&lt;/title&gt;
&lt;script language="javascript"&gt;
function replaceContent() {
	var table1 = document.getElementsByTagName("table")[0];
	var table2 = document.getElementsByTagName("table")[1];
	var kid1 = table1.firstChild.firstChild.firstChild; //定位到&lt;td&gt;节点
	var kid2 = table2.firstChild.firstChild.firstChild; //定位到&lt;td&gt;节点
	var repKid = kid2.firstChild; //定位到表格二&lt;td&gt;内含的TextNode节点
	try {
		//用表格二的单元格内容替换表格一的单元格内容，表格二变成没有单元格内容
		kid1.replaceChild(repKid,kid1.firstChild); 
		//下面注释如果开放，将出现object error，因为表格二已经被改变
		//kid2.replaceChild(kid1.firstChild,kid2.firstChild);
	}catch(e){
		alert(e);
	}
}
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;table width="200" border="1" cellspacing="0" cellpadding="0"&gt;
&lt;tbody&gt;
    &lt;tr&gt;
        &lt;td&gt;表格一&lt;/td&gt;
    &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;table width="200" border="1" cellspacing="0" cellpadding="0"&gt;
&lt;tbody&gt;
    &lt;tr&gt;
        &lt;td&gt;表格二&lt;/td&gt;
    &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;input type="button" name="replaceNode" value="替换" onClick="replaceContent()"&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre><p align="center"><img alt="" src="http://dev2dev.bea.com.cn/images/image051114015.jpg" /><img alt="" src="http://dev2dev.bea.com.cn/images/image051114016_0000.jpg" /></p><p>　　注意，当执行kid1.replaceChild(repKid,kid1.firstChild);的时候，table2的子节点已经被转移到table1了，table2已经没有子节点，不能再调用table2的子节点。看看代码的注释，试着运行一下，应该就知道文档是怎么改变的了。</p><p>　　<strong>D、往文档添加新内容<br /></strong>　　在学会遍历、搜索、修改文档之后，我们现在试着网文档添加新的内容。其实没有什么新意，只是利用我们上述提到的Node的属性和方法而已，还是操作&lt;table&gt;标记的内容。有新意的是，我们要实现一个留言簿。是的，留言簿，你可以往里面留言，只是不能刷新噢。</p><p>　　<strong>例子6 – sample5_1.htm：</strong></p><pre class="precode">&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;
&lt;title&gt;无标题文档&lt;/title&gt;
&lt;script language="javascript"&gt;
function insertStr() {
	var f = document.form1;
	var value = f.str.value;
	if(value!="") {
		// 从最终的TextNode节点开始，慢慢形成&lt;tbody&gt;结构
		var text = document.createTextNode(value); //新建一个TextNode节点
		var td = document.createElement("td"); //新建一个td类型的Element节点
		var tr = document.createElement("tr"); //新建一个tr类型的Element节点
		var tbody = document.createElement("tbody"); //新建一个tbody类型的Element节点
		td.appendChild(text); //将节点text加入td中
		tr.appendChild(td); //将节点td加入tr中
		tbody.appendChild(tr); //将节点tr加入tbody中
		var parNode = document.getElementById("table1"); //定位到table上
		parNode.insertBefore(tbody,parNode.firstChild); //将节点tbody插入到节点顶部
		//parNode.appendChild(tbody); //将节点tbody加入节点尾部
	}
}
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;form name="form1" method="post" action=""&gt;
    &lt;input name="str" type="text" id="str" value=""&gt;
    &lt;input name="insert" type="button" id="insert" value="留言" onClick="insertStr()"&gt;
&lt;/form&gt;
&lt;table width="400" border="1" cellspacing="0" cellpadding="0" id="table1"&gt;
&lt;tbody&gt;
    &lt;tr&gt;
        &lt;td height="25"&gt;网友留言列表：&lt;/td&gt;
    &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre><p>　　我们之前说过，&lt;table&gt;的子节点是&lt;tbody&gt;，&lt;tbody&gt;的子节点才是&lt;tr&gt;，&lt;tr&gt;是&lt;td&gt;的父节点，最后&lt;td&gt;内部的TextNode节点。所以，往&lt;table&gt;增加单元格行要逐级形成，就像往树里面添加一个枝桠一样，要有叶子有径。看看，这个留言簿是不是很简单啊。这个例子同时也演示了往&lt;table&gt;表格标记里面增加内容的另一种方法。</p><p align="center"><img alt="" src="http://dev2dev.bea.com.cn/images/image051114019.jpg" /><br /><img alt="" src="http://dev2dev.bea.com.cn/images/image051114020.jpg" /></p><p>　　<strong>E、使用DOM操作XML文档<br /></strong>　　在数据表示方面，XML文档更加结构化。DOM在支持HTML的基础上提供了一系列的API，支持针对XML的访问和操作。利用这些API，我们可以从XML中提取信息，动态的创建这些信息的HTML呈现文档。处理XML文档，通常遵循“加载XML文档à提取信息à加工信息à创建HTML文档”的过程。下面的例子演示了如何加载并处理XML文档。</p><p>　　这个例子包含两个JS函数。loadXML()负责加载XML文档，其中既包含加载XML文档的2级DOM代码，又有实现同样操作的Microsoft专有API代码。需要提醒注意的是，文档加载过程不是瞬间完成的，所以对loadXML()的调用将在加载文档完成之前返回。因此，需要传递给loadXML()一个引用，以便文档加载完成后调用。</p><p>　　例子中的另外一个函数makeTable()，则在XML文档加载完毕之后，使用最后前介绍过的DOM应用编程接口读取XML文档信息，并利用这些信息形成一个新的table表格。</p><p>　　<strong>例子7 -- sample6_1.htm：</strong></p><pre class="precode">&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;
&lt;title&gt;无标题文档&lt;/title&gt;
&lt;script language="javascript"&gt;
function loadXML(handler) {
	var url = "employees.xml";
	if(document.implementation&amp;&amp;document.implementation.createDocument) {
		var xmldoc = document.implementation.createDocument("", "", null);
		xmldoc.onload =  handler(xmldoc, url);
		xmldoc.load(url);
	}
	else if(window.ActiveXObject) {
		var xmldoc = new ActiveXObject("Microsoft.XMLDOM");
		xmldoc.onreadystatechange = function() {
			if(xmldoc.readyState == 4) handler(xmldoc, url);
		}
		xmldoc.load(url);
	}
}
function makeTable(xmldoc, url) {
	var table = document.createElement("table");
	table.setAttribute("border","1");
	table.setAttribute("width","600");
	table.setAttribute("class","tab-content");
	document.body.appendChild(table);
	var caption = "Employee Data from " + url;
	table.createCaption().appendChild(document.createTextNode(caption));
	var header = table.createTHead();
	var headerrow = header.insertRow(0);
	headerrow.insertCell(0).appendChild(document.createTextNode("姓名"));
	headerrow.insertCell(1).appendChild(document.createTextNode("职业"));
	headerrow.insertCell(2).appendChild(document.createTextNode("工资"));
	var employees = xmldoc.getElementsByTagName("employee");
	for(var i=0;i&lt;employees.length;i++) {
		var e = employees[i];
		var name = e.getAttribute("name");
		var job = e.getElementsByTagName("job")[0].firstChild.data;
		var salary = e.getElementsByTagName("salary")[0].firstChild.data;
		var row = table.insertRow(i+1);
		row.insertCell(0).appendChild(document.createTextNode(name));
		row.insertCell(1).appendChild(document.createTextNode(job));
		row.insertCell(2).appendChild(document.createTextNode(salary));
	}
}
&lt;/script&gt;
&lt;link href="css/style.css" rel="stylesheet" type="text/css"&gt;
&lt;/head&gt;

&lt;body onLoad="loadXML(makeTable)"&gt;
&lt;/body&gt;
&lt;/html&gt;<br /><strong>供读取调用的XML文档 – employees.xml：</strong><br />
&lt;?xml version="1.0" encoding="gb2312"?&gt;
&lt;employees&gt;
	&lt;employee name="J.Doe"&gt;
		&lt;job&gt;Programmer&lt;/job&gt;
		&lt;salary&gt;32768&lt;/salary&gt;
	&lt;/employee&gt;
	&lt;employee name="A.Baker"&gt;
		&lt;job&gt;Sales&lt;/job&gt;
		&lt;salary&gt;70000&lt;/salary&gt;
	&lt;/employee&gt;
	&lt;employee name="Big Cheese"&gt;
		&lt;job&gt;CEO&lt;/job&gt;
		&lt;salary&gt;100000&lt;/salary&gt;
	&lt;/employee&gt;
&lt;/employees&gt;
</pre><a name="a75"></a><strong>7.5、处理XML文档</strong><br />　　脱离XML文档的AJAX是不完整的。在本部分未完成之前，有读者说AJAX改名叫AJAH（H应该代表HTML吧）比较合适。应该承认，XML文档在数据的结构化表示以及接口对接上有先天的优势，但也不是所有的数据都应该用XML表示。有些时候单纯的文本表示可能会更合适。下面先举个AJAX处理返回XML文档的例子再讨论什么时候使用XML。<br /><br />7.5.1、处理返回的XML<br />　　 <strong>例子8 -- sample7_1.htm：<br /></strong>　　在这个例子中，我们采用之前确定的AJAX开发框架，稍微修改一下body内容和processRequest的相应方式，将先前的employees.xml的内容读取出来并显示。 
<p>　　body的内容如下：</p><pre class="precode">&lt;input type="button" name="read"
 value="读取XML" onClick="send_request('employees.xml')"&gt;
processRequest()方法修改如下：
	// 处理返回信息的函数
    function processRequest() {
        if (http_request.readyState == 4) { // 判断对象状态
            if (http_request.status == 200) { // 信息已经成功返回，开始处理信息
		var returnObj = http_request.responseXML;
		var xmlobj = http_request.responseXML;
		var employees = xmlobj.getElementsByTagName("employee");
		var feedbackStr = "";
		for(var i=0;i&lt;employees.length;i++) { // 循环读取employees.xml的内容
		var employee = employees[i];
		feedbackStr += "员工：" + employee.getAttribute("name");
		feedbackStr += 
" 职位：" + employee.getElementsByTagName("job")[0].firstChild.data;
		feedbackStr +=
 " 工资：" + employee.getElementsByTagName("salary")[0].firstChild.data;
		feedbackStr +=  "\r\n";
				}
				alert(feedbackStr);
            } else { //页面不正常
                alert("您所请求的页面有异常。");
            }
        }
}
</pre><p>　　运行一下，看来效果还不错：</p><p align="center"><img alt="" src="http://dev2dev.bea.com.cn/images/image051114028.jpg" /></p><a name="_Toc119127385"></a>7.5.2、选择合适的XML生成方式 
<p>　　现在的web应用程序往往采用了MVC三层剥离的设计方式。XML作为一种数据保存、呈现、交互的文档，其数据往往是动态生成的，通常由JavaBean转换过来。由JavaBean转换成XML文档的方式有好几种，选择合适的转换方式往往能达到事半功倍的效果。下面介绍两种常用的方式，以便需要的时候根据情况取舍。</p><p>　　<strong>A、类自行序列化成XML<br /></strong>　　类自行序列化成XML即每个类都实现自己的toXML()方法，选择合适的API、适当的XML结构、尽量便捷的生成逻辑快速生成相应的XML文档。显然，这种方式必须要求每个类编写专门的XML生成代码，每个类只能调用自己的toXML()方法。应用诸如JDOM等一些现成的API，可以减少不少开发投入。例子9是一个利用JDOM的API形成的toXML()<strong>方法。</strong></p><p>　　<strong>例子9 -- toXml() 的 JDOM 实现 -- Employ类的toXml()方法：</strong></p><pre class="precode">public Element toXml() {  
	Element employee = new Element(“employee”);
	Employee.setAttribute(“name”,name);
	Element jobE = new Element(“job”).addContent(job);
	employee.setContent(jobE);
	Element salaryE = new Element(“salary”).addContent(salary);
	employee.setContent(salaryE);
	return employee;
}
</pre><p>　　JDOM提供了现成的API，使得序列化成XML的工作更加简单，我们只需要把toXML()外面包装一个Document，然后使用XMLOutputter把文档写入servlet就可以了。toXml()允许递归调用其子类的toXML()方法，以便生成包含子图的XML文档。</p><p>　　使用类自行序列化成XML的方式，要每个类都实现自己的toXML()方法，而且存在数据模型与视图耦合的问题，即要么为每个可能的视图编写独立的toXML()方法，要么心甘情愿接收冗余的数据，一旦数据结构或者文档发生改变，toXML()就要做必要的修改。</p><p>　　<strong>B、页面模板生成XML方式<br /></strong>　　一般的，可以采用通用的页面模板技术来生成XML文档，这个XML文档可以符合任何需要的数据模型，供AJAX灵活的调用。另外，模板可以采用任何标记语言编写，提高工作效率。下面是一个采用Struts标签库编写的XML文档，输出之前提到的employees.xml：</p><p>　　<strong>Sample8_2.jsp：</strong></p><pre class="precode">&lt;%@ page contentType="application/xml; charset=gb2312" import="Employee"%&gt;
&lt;%@ page import="java.util.Collection,java.util.ArrayList"%&gt;
&lt;?xml version="1.0"?&gt;
&lt;%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %&gt;
&lt;%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%&gt;
&lt;%
Employee em1 = new Employee();
em1.setName("J.Doe");
em1.setJob("Programmer");
em1.setSalary("32768");
Employee em2 = new Employee();
em2.setName("A.Baker");
em2.setJob("Sales");
em2.setSalary("70000");
Employee em3 = new Employee();
em3.setName("Big Cheese");
em3.setJob("CEO");
em3.setSalary("100000");
Collection employees = new ArrayList();
employees.add(em1);
employees.add(em2);
employees.add(em3);
pageContext.setAttribute("employees",employees);
%&gt;
&lt;employees&gt;
&lt;logic:iterate name="employees" id="employee"&gt;
	&lt;employee name="&lt;bean:write name='employee' property='name'/&gt;"&gt;
		&lt;job&gt;&lt;bean:write name="employee" property="job"/&gt;&lt;/job&gt;
		&lt;salary&gt;&lt;bean:write name="employee" property="salary"/&gt;&lt;/salary&gt;
	&lt;/employee&gt;
&lt;/logic:iterate&gt;
&lt;/employees&gt;
</pre><p>　　<img alt="" src="http://dev2dev.bea.com.cn/images/image051114031.jpg" /></p><p>　　采用页面模板生成XML方式，需要为每个需要的的数据模型建立一个对立的JSP文件，用来生成符合规范的XML文档，而不能仅仅在类的toXML()方法中组织对象图来实现。不过，倒是可以更加方便的确保标记匹配、元素和属性的顺序正确以及XML实体正确转义。</p><p>　　参考资料中Philip McCarthy的文章还描述了一种Javascript对象标注的生成方式，本文在此不赘述。有兴趣的读者可以自行查看了解。</p><a></a>7.5.3、如何在使用XML还是普通文本间权衡<br />　　使用XML文档确实有其方便之处。不过XML文档的某些问题倒是要考虑一下，比如说延迟，即服务器不能立即解析XML文档成为DOM模型。这个问题在一定程度上会影响AJAX要求的快速反应能力。另外，某些情况下我们并不需要使用XML来表示数据，比如说数据足够简单成只有一个字符串而已。就好像我们之前提到的数据校验和级联菜单的例子一样。所以，个人认为在下面这些情况下可以考虑使用XML来作为数据表示的介质： 
<ul><li>数据比较复杂，需要用XML的结构化方式来表示 
</li><li>不用考虑带宽和处理效率支出 
</li><li>与系统其他API或者其他系统交互，作为一种数据中转中介 
</li><li>需要特定各式的输出视图而文本无法表示的 </li></ul><p>　　总之，要认真评估两种表示方式的表示成本和效率，选择合适的合理的表示方式。　　 </p><p>　　在关于AJAX的系列文章的下一篇，我们将综合使用DOM和XML，来实现一个可以持久化的简单留言簿。另外，还将试着模拟MSN Space的部分功能，来体会AJAX的魅力。<a name="a8"></a></p><a><strong>参考文章：</strong></a><br /><br /><table cellspacing="1" cellpadding="4" bgcolor="#000000"><tbody><tr bgcolor="#ffffff"><td valign="top" width="69">作者：</td><td valign="top" width="150">fanscial</td><td valign="top" width="75">标题：</td><td valign="top" width="416">《AJAX简介》</td></tr><tr bgcolor="#ffffff"><td valign="top" width="69">网址：</td><td valign="top" width="641" colspan="3"><a href="/fanscial/archive/2005/08/31/11628.html" target="_blank"><font color="#002c99">http://www.blogjava.net/fanscial/archive/2005/08/31/11628.html</font></a></td></tr><tr bgcolor="#ffffff"><td valign="top" width="69">作者：</td><td valign="top" width="150">Amour GUO</td><td valign="top" width="75">标题：</td><td valign="top" width="416">《AJAX内部交流文档》</td></tr><tr bgcolor="#ffffff"><td valign="top" width="69">网址：</td><td valign="top" width="641" colspan="3"><a href="http://www.dragonson.com/doc/ajax.html" target="_blank"><font color="#002c99">http://www.dragonson.com/doc/ajax.html</font></a></td></tr><tr bgcolor="#ffffff"><td valign="top" width="69">作者：</td><td valign="top" width="150">MoztwWiki</td><td valign="top" width="75">标题：</td><td valign="top" width="416">《AJAX上手篇》</td></tr><tr bgcolor="#ffffff"><td valign="top" width="69">网址：</td><td valign="top" width="641" colspan="3"><a href="http://wiki.moztw.org/index.php/AJAX_%E4%B8%8A%E6%89%8B%E7%AF%87" target="_blank"><font color="#002c99">http://wiki.moztw.org/index.php/AJAX_%E4%B8%8A%E6%89%8B%E7%AF%87</font></a></td></tr><tr bgcolor="#ffffff"><td valign="top" width="69">作者：</td><td valign="top" width="150">Philip McCarthy</td><td valign="top" width="75">标题：</td><td valign="top" width="416">面向Java开发人员的Ajax:构建动态的Java应用程序</td></tr><tr bgcolor="#ffffff"><td valign="top" width="69">网址：</td><td valign="top" width="641" colspan="3"><a href="http://kb.csdn.net/java/Articles/200510/bed0423e-5297-49c9-9464-0e3eb733c8b5.html" target="_blank"><font color="#002c99">http://kb.csdn.net/java/Articles/200510/bed0423e-5297-49c9-9464-0e3eb733c8b5.html</font></a></td></tr><tr bgcolor="#ffffff"><td valign="top" width="69">作者：</td><td valign="top" width="150">Philip McCarthy</td><td valign="top" width="75">标题：</td><td valign="top" width="416">面向Java开发人员的Ajax:Ajax的Java对象序列化</td></tr><tr bgcolor="#ffffff"><td valign="top" width="69">网址：</td><td valign="top" width="641" colspan="3"><a href="http://kb.csdn.net/java/Articles/200510/a5b630cf-a2c2-46f1-8e3b-eadde723e734.html" target="_blank"><font color="#002c99">http://kb.csdn.net/java/Articles/200510/a5b630cf-a2c2-46f1-8e3b-eadde723e734.html</font></a></td></tr><tr bgcolor="#ffffff"><td valign="top" width="69">作者：</td><td valign="top" width="150">David Flanagan</td><td valign="top" width="75">书名：</td><td valign="top" width="416">《Javascript权威指南》</td></tr></tbody></table><p> </p><img src ="http://www.blogjava.net/iKingQu/aggbug/36524.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iKingQu/" target="_blank">風向逆轉 - 就要爪哇</a> 2006-03-21 00:41 <a href="http://www.blogjava.net/iKingQu/articles/36524.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[收藏]AJAX开发简略 (一) </title><link>http://www.blogjava.net/iKingQu/articles/36522.html</link><dc:creator>風向逆轉 - 就要爪哇</dc:creator><author>風向逆轉 - 就要爪哇</author><pubDate>Mon, 20 Mar 2006 16:38:00 GMT</pubDate><guid>http://www.blogjava.net/iKingQu/articles/36522.html</guid><wfw:comment>http://www.blogjava.net/iKingQu/comments/36522.html</wfw:comment><comments>http://www.blogjava.net/iKingQu/articles/36522.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/iKingQu/comments/commentRss/36522.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iKingQu/services/trackbacks/36522.html</trackback:ping><description><![CDATA[
		<p>　　现在，有一种越来越流行越热的“老”技术，可以彻底改变这种窘迫的局面。那就是AJAX。如今，随着Gmail、Google-maps的应用和各种浏览器的支持，AJAX正逐渐吸引全世界的眼球。</p>
		<a>
				<strong>一、AJAX定义</strong>
		</a>
		<br />　　 AJAX（Asynchronous JavaScript and XML）其实是多种技术的综合，包括Javascript、XHTML和CSS、DOM、XML和XSTL、XMLHttpRequest。其中： 
<p>　　使用XHTML和CSS标准化呈现，使用DOM实现动态显示和交互，使用XML和XSTL进行数据交换与处理，使用XMLHttpRequest对象进行异步数据读取，使用Javascript绑定和处理所有数据。</p><p>　　在AJAX提出之前，业界对于上述技术都只是单独的使用，没有综合使用，也是由于之前的技术需求所决定的。随着应用的广泛，AJAX也成为香饽饽了。</p><a><strong>二、现状与需要解决的问题</strong></a><br />　　传统的Web应用采用同步交互过程，这种情况下，用户首先向HTTP服务器触发一个行为或请求的呼求。反过来，服务器执行某些任务，再向发出请求的用户返回一个HTML页面。这是一种不连贯的用户体验，服务器在处理请求的时候，用户多数时间处于等待的状态，屏幕内容也是一片空白。如下图： 
<p align="center"><img alt="" src="http://dev2dev.bea.com.cn/images/images051114001.jpg" /></p><p align="center"><img alt="" src="http://dev2dev.bea.com.cn/images/images051114002.jpg" /></p><p>　　自从采用超文本作为Web传输和呈现之后，我们都是采用这么一套传输方式。当负载比较小的时候，这并不会体现出有什么不妥。可是当负载比较大，响应时间要很长，1分钟、2分钟……数分钟的时候，这种等待就不可忍受了。严重的，超过响应时间，服务器干脆告诉你页面不可用。另外，某些时候，我只是想改变页面一小部分的数据，那为什么我必须重新加载整个页面呢？！当软件设计越来越讲究人性化的时候，这么糟糕的用户体验简直与这种原则背道而驰。为什么老是要让用户等待服务器取数据呢？至少，我们应该减少用户等待的时间。现在，除了程序设计、编码优化和服务器调优之外，还可以采用AJAX。</p><a><strong>三、为什么使用AJAX</strong></a><br />　　与传统的Web应用不同，AJAX采用异步交互过程。AJAX在用户与服务器之间引入一个中间媒介，从而消除了网络交互过程中的处理—等待—处理—等待缺点。用户的浏览器在执行任务时即装载了AJAX引擎。AJAX引擎用JavaScript语言编写，通常藏在一个隐藏的框架中。它负责编译用户界面及与服务器之间的交互。AJAX引擎允许用户与应用软件之间的交互过程异步进行，独立于用户与网络服务器间的交流。现在，可以用Javascript调用AJAX引擎来代替产生一个HTTP的用户动作，内存中的数据编辑、页面导航、数据校验这些不需要重新载入整个页面的需求可以交给AJAX来执行。 
<p align="center"><img alt="" src="http://dev2dev.bea.com.cn/images/images051114003.jpg" /></p><p align="center"><img alt="" src="http://dev2dev.bea.com.cn/images/images051114004.jpg" /></p><p>　　使用AJAX，可以为ISP、开发人员、终端用户带来可见的便捷：</p><ul><li>减轻服务器的负担。AJAX的原则是“按需取数据”，可以最大程度的减少冗余请求，和响应对服务器造成的负担。 
</li><li>无刷新更新页面，减少用户心理和实际的等待时间。特别的，当要读取大量的数据的时候，不用像Reload那样出现白屏的情况，AJAX使用XMLHTTP对象发送请求并得到服务器响应，在不重新载入整个页面的情况下用Javascript操作DOM最终更新页面。所以在读取数据的过程中，用户所面对的不是白屏，是原来的页面内容（也可以加一个Loading的提示框让用户知道处于读取数据过程），只有当数据接收完毕之后才更新相应部分的内容。这种更新是瞬间的，用户几乎感觉不到。 
</li><li>带来更好的用户体验。 
</li><li>可以把以前一些服务器负担的工作转嫁到客户端，利用客户端闲置的能力来处理，减轻服务器和带宽的负担，节约空间和宽带租用成本。 
</li><li>可以调用外部数据。 
</li><li>基于标准化的并被广泛支持的技术，不需要下载插件或者小程序。 
</li><li>进一步促进页面呈现和数据的分离。 </li></ul><a><strong>四、谁在使用AJAX</strong></a><br />　　在应用AJAX开发上面，Google当仁不让是表率。Orkut、Gmail、Google Groups、Google Maps、Google Suggest都应用了这项技术。Amazon的A9.com搜索引擎也采用了类似的技术。 
<p>　　微软也在积极开发更为完善的AJAX应用：它即将推出代号为Atlas的AJAX工具。Atlas的功能超越了AJAX本身，包括整合Visual Studio的调试功能。另外，新的ASP.NET控件将使客户端控件与服务器端代码的捆绑更为简便。Atlas客户脚本框架（Atlas Clent Script Framework）也使与网页及相关项目的交互更为便利。但Visual Studio 2005中并不包含此项功能。</p><p>　　微软最近宣布Atlas客户脚本框架将包含如下内容（详细资料请访问Atlas计划网站）：</p><ul><li>一个可扩展的核心框架，它添加了JavaScript功能：如生命同时期管理、继承管理、多点传送处理器和界面管理。 
</li><li>一个常见功能的基本类库，有丰富的字符串处理、计时器和运行任务。 
</li><li>为HTML附加动态行为的用户界面框架。 
</li><li>一组用来简化服务器连通和网络访问的网络堆栈。 
</li><li>一组丰富的用户界面开发控件，如：自动完成的文本框、动画和拖放。 
</li><li>处理浏览器脚本行为差异的浏览器兼容层面。 </li></ul><p>　　典型的，微软将AJAX技术应用在MSN Space上面。很多人一直都对MS Space服务感到很奇怪，当提交回复评论以后，浏览器会暂时停顿一下，然后在无刷新的情况下把我提交的评论显示出来。这个就是应用了AJAX的效果。试想，如果添加一个评论就要重新刷新整个页面，那可真费事。</p><p>　　目前，AJAX应用最普遍的领域是GIS-Map方面。GIS的区域搜索强调快速响应，AJAX的特点正好符合这种需求。</p><a><strong>五、用AJAX改进你的设计</strong></a><br />　　 AJAX虽然可以实现无刷新更新页面内容，但是也不是什么地方都可以用，主要应用在交互较多、频繁读数据、数据分类良好的Web应用中。现在，让我们举两个例子，看看如何用AJAX改进你的设计。<a><br /><br />例子1：数据校验<br /></a>　　在输入form表单内容的时候，我们通常需要确保数据的唯一性。因此，常常在页面上提供“唯一性校验”按钮，让用户点击，打开一个校验小窗口；或者等form提交到服务器端，由服务器判断后在返回相应的校验信息。前者，window.open操作本来就是比较耗费资源的，通常由window. showModalDialog代替，即使这样也要弹出一个对话框；后者，需要把整个页面提交到服务器并由服务器判断校验，这个过程不仅时间长而且加重了服务器负担。而使用AJAX，这个校验请求可以由XMLHttpRequest对象发出，整个过程不需要弹出新窗口，也不需要将整个页面提交到服务器，快速又不加重服务器负担。<a>例子2：按需取数据—级联菜单<br /></a>　　以前，为了避免每次对菜单的操作引起的重载页面，不采用每次调用后台的方式，而是一次性将级联菜单的所有数据全部读取出来并写入数组，然后根据用户的操作用JavaScript来控制它的子集项目的呈现，这样虽然解决了操作响应速度、不重载页面以及避免向服务器频繁发送请求的问题，但是如果用户不对菜单进行操作或只对菜单中的一部分进行操作的话，那读取的数据中的一部分就会成为冗余数据而浪费用户的资源，特别是在菜单结构复杂、数据量大的情况下（比如菜单有很多级、每一级菜又有上百个项目），这种弊端就更为突出。 
<p>　　现在应用AJAX，在初始化页面时我们只读出它的第一级的所有数据并显示，在用户操作一级菜单其中一项时，会通过Ajax向后台请求当前一级项目所属的二级子菜单的所有数据，如果再继续请求已经呈现的二级菜单中的一项时，再向后面请求所操作二级菜单项对应的所有三级菜单的所有数据，以此类推……这样，用什么就取什么、用多少就取多少，就不会有数据的冗余和浪费，减少了数据下载总量，而且更新页面时不用重载全部内容，只更新需要更新的那部分即可，相对于后台处理并重载的方式缩短了用户等待时间，也把对资源的浪费降到最低。</p><a>例子3：读取外部数据<br /></a>　　AJAX可以调用外部数据，因此，可以对一些开发的数据比如XML文档、RSS文档进行二次加工，实现数据整合或者开发应用程序。<a>六、AJAX的缺陷</a><p>　　AJAX不是完美的技术。使用AJAX，它的一些缺陷不得不权衡一下：</p><ul><li>AJAX大量使用了Javascript和AJAX引擎，而这个取决于浏览器的支持。IE5.0及以上、Mozilla1.0、NetScape7及以上版本才支持，Mozilla虽然也支持AJAX，但是提供XMLHttpRequest的方式不一样。所以，使用AJAX的程序必须测试针对各个浏览器的兼容性。 
</li><li>AJAX更新页面内容的时候并没有刷新整个页面，因此，网页的后退功能是失效的；有的用户还经常搞不清楚现在的数据是旧的还是已经更新过的。这个就需要在明显位置提醒用户“数据已更新”。 
</li><li>对流媒体的支持没有FLASH、Java Applet好。 
</li><li>一些手持设备（如手机、PDA等）现在还不能很好的支持Ajax。</li></ul><img src ="http://www.blogjava.net/iKingQu/aggbug/36522.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iKingQu/" target="_blank">風向逆轉 - 就要爪哇</a> 2006-03-21 00:38 <a href="http://www.blogjava.net/iKingQu/articles/36522.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[收藏]Ajax 简介(二) </title><link>http://www.blogjava.net/iKingQu/articles/36521.html</link><dc:creator>風向逆轉 - 就要爪哇</dc:creator><author>風向逆轉 - 就要爪哇</author><pubDate>Mon, 20 Mar 2006 16:33:00 GMT</pubDate><guid>http://www.blogjava.net/iKingQu/articles/36521.html</guid><wfw:comment>http://www.blogjava.net/iKingQu/comments/36521.html</wfw:comment><comments>http://www.blogjava.net/iKingQu/articles/36521.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/iKingQu/comments/commentRss/36521.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iKingQu/services/trackbacks/36521.html</trackback:ping><description><![CDATA[
		<p>
				<font color="#996699">Brett McLaughlin </font>, 作家，编辑, O'Reilly and Associates<br /></p>
		<p>2006 年 1 月 04 日</p>
		<p>五年前，如果不知道 XML，您就是一只无人重视的丑小鸭。十八个月前，Ruby 成了关注的中心，不知道 Ruby 的程序员只能坐冷板凳了。今天，如果想跟上最新的技术时尚，那您的目标就是 Ajax。</p>
		<p>但是，Ajax 不<em>仅仅</em> 是一种时尚，它是一种构建网站的强大方法，而且不像学习一种全新的语言那样困难。</p>
		<p>但在详细探讨 Ajax 是什么之前，先让我们花几分钟了解 Ajax <em>做</em> 什么。目前，编写应用程序时有两种基本的选择：</p>
		<ul>
				<li>桌面应用程序 
</li>
				<li>Web 应用程序 </li>
		</ul>
		<p>两者是类似的，桌面应用程序通常以 CD 为介质（有时候可从网站下载）并完全安装到您的计算机上。桌面应用程序可能使用互联网下载更新，但运行这些应用程序的代码在桌面计算机上。Web 应用程序运行在某处的 Web 服务器上 —— 毫不奇怪，要通过 Web 浏览器访问这种应用程序。</p>
		<p>不过，比这些应用程序的运行代码放在何处更重要的是，应用程序如何运转以及如何与其进行交互。桌面应用程序一般很快（就在您的计算机上运行，不用等待互联网连接），具有漂亮的用户界面（通常和操作系统有关）和非凡的动态性。可以单击、选择、输入、打开菜单和子菜单、到处巡游，基本上不需要等待。</p>
		<p>另一方面，Web 应用程序是最新的潮流，它们提供了在桌面上不能实现的服务（比如 Amazon.com 和 eBay）。但是，伴随着 Web 的强大而出现的是等待，等待服务器响应，等待屏幕刷新，等待请求返回和生成新的页面。</p>
		<p>显然这样说过于简略了，但基本的概念就是如此。您可能已经猜到，Ajax 尝试建立桌面应用程序的功能和交互性，与不断更新的 Web 应用程序之间的桥梁。可以使用像桌面应用程序中常见的动态用户界面和漂亮的控件，不过是在 Web 应用程序中。</p>
		<p>还等什么呢？我们来看看 Ajax 如何将笨拙的 Web 界面转化成能迅速响应的 Ajax 应用程序吧。</p>
		<p>
				<a name="IDAWDSFB">
						<span class="atitle">
								<font size="4">老技术，新技巧</font>
						</span>
				</a>
		</p>
		<p>在谈到 Ajax 时，实际上涉及到多种技术，要灵活地运用它必须深入了解这些不同的技术（本系列的头几篇文章将分别讨论这些技术）。好消息是您可能已经非常熟悉其中的大部分技术，更好的是这些技术都很容易学习，并不像完整的编程语言（如 Java 或 Ruby）那样困难。</p>
		<p>
		</p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="IDA3DSFB">
																				<strong>Ajax 的定义</strong>
																		</a>
																		<br />
																		<p>顺便说一下，Ajax 是 Asynchronous JavaScript and XML（以及 DHTML 等）的缩写。这个短语是 Adaptive Path 的 Jesse James Garrett 发明的（请参阅 <a href="http://blog.csdn.net/baggio785/archive/2006/01/06/571779.aspx#resources"><font color="#996699">参考资料</font></a>），按照 Jesse 的解释，这<em>不是</em> 个首字母缩写词。</p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<p>下面是 Ajax 应用程序所用到的基本技术：</p>
		<ul>
				<li>HTML 用于建立 Web 表单并确定应用程序其他部分使用的字段。 
</li>
				<li>JavaScript 代码是运行 Ajax 应用程序的核心代码，帮助改进与服务器应用程序的通信。 
</li>
				<li>DHTML 或 Dynamic HTML，用于动态更新表单。我们将使用 <code>div</code>、<code>span</code> 和其他动态 HTML 元素来标记 HTML。 
</li>
				<li>文档对象模型 DOM 用于（通过 JavaScript 代码）处理 HTML 结构和（某些情况下）服务器返回的 XML。 </li>
		</ul>
		<p>我们来进一步分析这些技术的职责。以后的文章中我将深入讨论这些技术，目前只要熟悉这些组件和技术就可以了。对这些代码越熟悉，就越容易从对这些技术的零散了解转变到真正把握这些技术（同时也真正打开了 Web 应用程序开发的大门）。</p>
		<p>
				<a name="IDAZESFB">
						<span class="smalltitle">
								<strong>
										<font size="3">XMLHttpRequest 对象</font>
								</strong>
						</span>
				</a>
		</p>
		<p>要了解的一个对象可能对您来说也是最陌生的，即 <code>XMLHttpRequest</code>。这是一个 JavaScript 对象，创建该对象很简单，如<font color="#996699">清单 1</font> 所示。</p>
		<p>
				<br />
				<a name="code1">
						<strong>清单 1. 创建新的 XMLHttpRequest 对象</strong>
				</a>
				<br />
		</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;script language="javascript" type="text/javascript"&gt;
var xmlHttp = new XMLHttpRequest();
&lt;/script&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>下一期文章中将进一步讨论这个对象，现在要知道这是处理所有服务器通信的对象。继续阅读之前，先停下来想一想：通过 <code>XMLHttpRequest</code> 对象与服务器进行对话的是 <em>JavaScript</em> 技术。这不是一般的应用程序流，这恰恰是 Ajax 的强大功能的来源。</p>
		<p>在一般的 Web 应用程序中，用户填写表单字段并单击 <em>Submit</em> 按钮。然后整个表单发送到服务器，服务器将它转发给处理表单的脚本（通常是 PHP 或 Java，也可能是 CGI 进程或者类似的东西），脚本执行完成后再发送回全新的页面。该页面可能是带有已经填充某些数据的新表单的 HTML，也可能是确认页面，或者是具有根据原来表单中输入数据选择的某些选项的页面。当然，在服务器上的脚本或程序处理和返回新表单时用户必须等待。屏幕变成一片空白，等到服务器返回数据后再重新绘制。这就是交互性差的原因，用户得不到立即反馈，因此感觉不同于桌面应用程序。</p>
		<p>Ajax 基本上就是把 JavaScript 技术和 <code>XMLHttpRequest</code> 对象放在 Web 表单和服务器<em>之间</em>。当用户填写表单时，数据发送给一些 JavaScript 代码而<em>不是</em> 直接发送给服务器。相反，JavaScript 代码捕获表单数据并向服务器发送请求。同时用户屏幕上的表单也不会闪烁、消失或延迟。换句话说，JavaScript 代码在幕后发送请求，用户甚至不知道请求的发出。更好的是，请求是异步发送的，就是说 JavaScript 代码（和用户）不用等待服务器的响应。因此用户可以继续输入数据、滚动屏幕和使用应用程序。</p>
		<p>然后，服务器将数据返回 JavaScript 代码（仍然在 Web 表单中），后者决定如何处理这些数据。它可以迅速更新表单数据，让人感觉应用程序是立即完成的，表单没有提交或刷新而用户得到了新数据。JavaScript 代码甚至可以对收到的数据执行某种计算，再发送另一个请求，完全不需要用户干预！这就是 <code>XMLHttpRequest</code> 的强大之处。它可以根据需要自行与服务器进行交互，用户甚至可以完全不知道幕后发生的一切。结果就是类似于桌面应用程序的动态、快速响应、高交互性的体验，但是背后又拥有互联网的全部强大力量。</p>
		<p>
				<a name="IDALGSFB">
						<span class="smalltitle">
								<strong>
										<font size="3">加入一些 JavaScript</font>
								</strong>
						</span>
				</a>
		</p>
		<p>得到 <code>XMLHttpRequest</code> 的句柄后，其他的 JavaScript 代码就非常简单了。事实上，我们将使用 JavaScript 代码完成非常基本的任务：</p>
		<ul>
				<li>获取表单数据：JavaScript 代码很容易从 HTML 表单中抽取数据并发送到服务器。 
</li>
				<li>修改表单上的数据：更新表单也很简单，从设置字段值到迅速替换图像。 
</li>
				<li>解析 HTML 和 XML：使用 JavaScript 代码操纵 DOM（请参阅 <a href="http://blog.csdn.net/baggio785/archive/2006/01/06/571779.aspx#dom"><font color="#996699">下一节</font></a>），处理 HTML 表单服务器返回的 XML 数据的结构。 </li>
		</ul>
		<p>对于前两点，需要非常熟悉 <code>getElementById()</code> 方法，如 <font color="#996699">清单 2</font> 所示。</p>
		<p>
				<br />
				<a name="code2">
						<strong>清单 2. 用 JavaScript 代码捕获和设置字段值</strong>
				</a>
				<br />
		</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">// Get the value of the "phone" field and stuff it in a variable called phone
var phone = document.getElementById("phone").value;

// Set some values on a form using an array called response
document.getElementById("order").value = response[0];
document.getElementById("address").value = response[1];
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>这里没有特别需要注意的地方，真是好极了！您应该认识到这里并没有非常复杂的东西。只要掌握了 <code>XMLHttpRequest</code>，Ajax 应用程序的其他部分就是如 <font color="#996699">清单 2</font> 所示的简单 JavaScript 代码了，混合有少量的 HTML。同时，还要用一点儿 DOM，我们就来看看吧。</p>
		<p>
				<a name="dom">
						<span class="smalltitle">
								<strong>
										<font size="3">以 DOM 结束</font>
								</strong>
						</span>
				</a>
		</p>
		<p>最后还有 DOM，即文档对象模型。可能对有些读者来说 DOM 有点儿令人生畏，HTML 设计者很少使用它，即使 JavaScript 程序员也不大用到它，除非要完成某项高端编程任务。大量使用 DOM 的<em>是</em> 复杂的 Java 和 C/C++ 程序，这可能就是 DOM 被认为难以学习的原因。</p>
		<p>幸运的是，在 JavaScript 技术中使用 DOM 很容易，也非常直观。现在，按照常规也许应该说明如何使用 DOM，或者至少要给出一些示例代码，但这样做也可能误导您。即使不理会 DOM，仍然能深入地探讨 Ajax，这也是我准备采用的方法。以后的文章将再次讨论 DOM，现在只要知道可能需要 DOM 就可以了。当需要在 JavaScript 代码和服务器之间传递 XML 和改变 HTML 表单的时候，我们再深入研究 DOM。没有它也能做一些有趣的工作，因此现在就把 DOM 放到一边吧。</p>
		<p>
				<br />
				<a name="IDAGAYW">
						<span class="atitle">
								<font size="4">获取 Request 对象</font>
						</span>
				</a>
		</p>
		<p>有了上面的基础知识后，我们来看看一些具体的例子。<code>XMLHttpRequest</code> 是 Ajax 应用程序的核心，而且对很多读者来说可能还比较陌生，我们就从这里开始吧。从 <a href="http://blog.csdn.net/baggio785/archive/2006/01/06/571779.aspx#code1"><font color="#996699">清单 1</font></a> 可以看出，创建和使用这个对象非常简单，不是吗？等一等。</p>
		<p>还记得几年前的那些讨厌的浏览器战争吗？没有一样东西在不同的浏览器上得到同样的结果。不管您是否相信，这些战争仍然在继续，虽然规模较小。但令人奇怪的是，<code>XMLHttpRequest</code> 成了这场战争的牺牲品之一。因此获得 <code>XMLHttpRequest</code> 对象可能需要采用不同的方法。下面我将详细地进行解释。</p>
		<p>
				<a name="IDA5AYW">
						<span class="smalltitle">
								<strong>
										<font size="3">使用 Microsoft 浏览器</font>
								</strong>
						</span>
				</a>
		</p>
		<p>Microsoft 浏览器 Internet Explorer 使用 MSXML 解析器处理 XML（可以通过 <a href="http://blog.csdn.net/baggio785/archive/2006/01/06/571779.aspx#resources"><font color="#996699">参考资料</font></a> 进一步了解 MSXML）。因此如果编写的 Ajax 应用程序要和 Internet Explorer 打交道，那么必须用一种特殊的方式创建对象。</p>
		<p>但并不是这么简单。根据 Internet Explorer 中安装的 JavaScript 技术版本不同，MSXML 实际上有两种不同的版本，因此必须对这两种情况分别编写代码。请参阅 <font color="#996699">清单 3</font>，其中的代码在 Microsoft 浏览器上创建了一个 <code>XMLHttpRequest</code>。</p>
		<p>
				<br />
				<a name="code3">
						<strong>清单 3. 在 Microsoft 浏览器上创建 XMLHttpRequest 对象</strong>
				</a>
				<br />
		</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">var xmlHttp = false;
try {
  xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
  try {
    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (e2) {
    xmlHttp = false;
  }
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>您对这些代码可能还不完全理解，但没有关系。当本系列文章结束的时候，您将对 JavaScript 编程、错误处理、条件编译等有更深的了解。现在只要牢牢记住其中的两行代码：</p>
		<p>
				<code>xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");</code>
		</p>
		<p>和</p>
		<p>
				<code>xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");</code>。</p>
		<p>这两行代码基本上就是尝试使用一个版本的 MSXML 创建对象，如果失败则使用另一个版本创建该对象。不错吧？如果都不成功，则将 <code>xmlHttp</code> 变量设为 false，告诉您的代码出现了问题。如果出现这种情况，可能是因为安装了非 Microsoft 浏览器，需要使用不同的代码。</p>
		<p>
				<a name="IDANCYW">
						<span class="smalltitle">
								<strong>
										<font size="3">处理 Mozilla 和非 Microsoft 浏览器</font>
								</strong>
						</span>
				</a>
		</p>
		<p>如果选择的浏览器不是 Internet Explorer，或者为非 Microsoft 浏览器编写代码，就需要使用不同的代码。事实上就是 <a href="http://blog.csdn.net/baggio785/archive/2006/01/06/571779.aspx#code1"><font color="#996699">清单 1</font></a> 所示的一行简单代码：</p>
		<p>
				<code>var xmlHttp = new XMLHttpRequest object;</code>。</p>
		<p>这行简单得多的代码在 Mozilla、Firefox、Safari、Opera 以及基本上所有以任何形式或方式支持 Ajax 的非 Microsoft 浏览器中，创建了 <code>XMLHttpRequest</code> 对象。</p>
		<p>
				<a name="IDACDYW">
						<span class="smalltitle">
								<strong>
										<font size="3">结合起来</font>
								</strong>
						</span>
				</a>
		</p>
		<p>关键是要支持<em>所有</em> 浏览器。谁愿意编写一个只能用于 Internet Explorer 或者非 Microsoft 浏览器的应用程序呢？或者更糟，要编写一个应用程序两次？当然不！因此代码要同时支持 Internet Explorer 和非 Microsoft 浏览器。<font color="#996699">清单 4</font> 显示了这样的代码。</p>
		<p>
				<br />
				<a name="code4">
						<strong>清单 4. 以支持多种浏览器的方式创建 XMLHttpRequest 对象</strong>
				</a>
				<br />
		</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">/* Create a new XMLHttpRequest object to talk to the Web server */
var xmlHttp = false;
/*@cc_on @*/
/*@if (@_jscript_version &gt;= 5)
try {
  xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
  try {
    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (e2) {
    xmlHttp = false;
  }
}
@end @*/

if (!xmlHttp &amp;&amp; typeof XMLHttpRequest != 'undefined') {
  xmlHttp = new XMLHttpRequest();
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>现在先不管那些注释掉的奇怪符号，如 <code>@cc_on</code>，这是特殊的 JavaScript 编译器命令，将在下一期针对 <code>XMLHttpRequest</code> 的文章中详细讨论。这段代码的核心分为三步：</p>
		<ol>
				<li>建立一个变量 <code>xmlHttp</code> 来引用即将创建的 <code>XMLHttpRequest</code> 对象。 
</li>
				<li>尝试在 Microsoft 浏览器中创建该对象： 
<ul><li>尝试使用 <code>Msxml2.XMLHTTP</code> 对象创建它。 
</li><li>如果失败，再尝试 <code>Microsoft.XMLHTTP</code> 对象。 </li></ul></li>
				<li>如果仍然没有建立 <code>xmlHttp</code>，则以非 Microsoft 的方式创建该对象。 </li>
		</ol>
		<p>最后，<code>xmlHttp</code> 应该引用一个有效的 <code>XMLHttpRequest</code> 对象，无论运行什么样的浏览器。</p>
		<p>
				<a name="IDALFYW">
						<span class="smalltitle">
								<strong>
										<font size="3">关于安全性的一点说明</font>
								</strong>
						</span>
				</a>
		</p>
		<p>安全性如何呢？现在浏览器允许用户提高他们的安全等级，关闭 JavaScript 技术，禁用浏览器中的任何选项。在这种情况下，代码无论如何都不会工作。此时必须适当地处理问题，这需要单独的一篇文章来讨论，要放到以后了（这个系列够长了吧？不用担心，读完之前也许您就掌握了）。现在要编写一段健壮但不够完美的代码，对于掌握 Ajax 来说就很好了。以后我们还将讨论更多的细节。</p>
		<p>
				<br />
				<a name="IDAQFYW">
						<span class="atitle">
								<font size="4">Ajax 世界中的请求/响应</font>
						</span>
				</a>
		</p>
		<p>现在我们介绍了 Ajax，对 <code>XMLHttpRequest</code> 对象以及如何创建它也有了基本的了解。如果阅读得很仔细，您可能已经知道与服务器上的 Web 应用程序打交道的是 JavaScript 技术，而不是直接提交给那个应用程序的 HTML 表单。</p>
		<p>还缺少什么呢？到底如何使用 <code>XMLHttpRequest</code>。因为这段代码非常重要，您编写的<em>每个</em> Ajax 应用程序都要以某种形式使用它，先看看 Ajax 的基本请求/响应模型是什么样吧。</p>
		<p>
				<a name="IDADGYW">
						<span class="smalltitle">
								<strong>
										<font size="3">发出请求</font>
								</strong>
						</span>
				</a>
		</p>
		<p>您已经有了一个崭新的 <code>XMLHttpRequest</code> 对象，现在让它干点活儿吧。首先需要一个 Web 页面能够调用的 JavaScript 方法（比如当用户输入文本或者从菜单中选择一项时）。接下来就是在所有 Ajax 应用程序中基本都雷同的流程：</p>
		<ol>
				<li>从 Web 表单中获取需要的数据。 
</li>
				<li>建立要连接的 URL。 
</li>
				<li>打开到服务器的连接。 
</li>
				<li>设置服务器在完成后要运行的函数。 
</li>
				<li>发送请求。 </li>
		</ol>
		<p>
				<font color="#996699">清单 5</font> 中的示例 Ajax 方法就是按照这个顺序组织的：</p>
		<p>
				<br />
				<a name="code5">
						<strong>清单 5. 发出 Ajax 请求</strong>
				</a>
				<br />
		</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">function callServer() {
  // Get the city and state from the web form
  var city = document.getElementById("city").value;
  var state = document.getElementById("state").value;
  // Only go on if there are values for both fields
  if ((city == null) || (city == "")) return;
  if ((state == null) || (state == "")) return;

  // Build the URL to connect to
  var url = "/scripts/getZipCode.php?city=" + escape(city) + "&amp;state=" + escape(state);

  // Open a connection to the server
  xmlHttp.open("GET", url, true);

  // Setup a function for the server to run when it's done
  xmlHttp.onreadystatechange = updatePage;

  // Send the request
  xmlHttp.send(null);
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>其中大部分代码意义都很明确。开始的代码使用基本 JavaScript 代码获取几个表单字段的值。然后设置一个 PHP 脚本作为链接的目标。要注意脚本 URL 的指定方式，city 和 state（来自表单）使用简单的 GET 参数附加在 URL 之后。</p>
		<p>然后打开一个连接，这是您第一次看到使用 <code>XMLHttpRequest</code>。其中指定了连接方法（GET）和要连接的 URL。最后一个参数如果设为 <code>true</code>，那么将请求一个异步连接（这就是 Ajax 的由来）。如果使用 <code>false</code>，那么代码发出请求后将等待服务器返回的响应。如果设为 <code>true</code>，当服务器在后台处理请求的时候用户仍然可以使用表单（甚至调用其他 JavaScript 方法）。</p>
		<p>
				<code>xmlHttp</code>（要记住，这是 <code>XMLHttpRequest</code> 对象实例）的 <code>onreadystatechange</code> 属性可以告诉服务器在运行<em>完成</em> 后（可能要用五分钟或者五个小时）做什么。因为代码没有等待服务器，必须让服务器知道怎么做以便您能作出响应。在这个示例中，如果服务器处理完了请求，一个特殊的名为 <code>updatePage()</code> 的方法将被触发。</p>
		<p>最后，使用值 <code>null</code> 调用 <code>send()</code>。因为已经在请求 URL 中添加了要发送给服务器的数据（city 和 state），所以请求中不需要发送任何数据。这样就发出了请求，服务器按照您的要求工作。</p>
		<p>如果没有发现任何新鲜的东西，您应该体会到这是多么简单明了！除了牢牢记住 Ajax 的异步特性外，这些内容都相当简单。应该感激 Ajax 使您能够专心编写漂亮的应用程序和界面，而不用担心复杂的 HTTP 请求/响应代码。</p>
		<p>
				<a href="http://blog.csdn.net/baggio785/archive/2006/01/06/571779.aspx#code5">
						<font color="#996699">清单 5</font>
				</a>中的代码说明了 Ajax 的易用性。数据是简单的文本，可以作为请求 URL 的一部分。用 GET 而不是更复杂的 POST 发送请求。没有 XML 和要添加的内容头部，请求体中没有要发送的数据；换句话说，这就是 Ajax 的乌托邦。</p>
		<p>不用担心，随着本系列文章的展开，事情会变得越来越复杂。您将看到如何发送 POST 请求、如何设置请求头部和内容类型、如何在消息中编码 XML、如何增加请求的安全性，可以做的工作还有很多！暂时先不用管那些难点，掌握好基本的东西就行了，很快我们就会建立一整套的 Ajax 工具库。</p>
		<p>
				<a name="IDA1IYW">
						<span class="smalltitle">
								<strong>
										<font size="3">处理响应</font>
								</strong>
						</span>
				</a>
		</p>
		<p>现在要面对服务器的响应了。现在只要知道两点：</p>
		<ul>
				<li>什么也不要做，直到 <code>xmlHttp.readyState</code> 属性的值等于 4。 
</li>
				<li>服务器将把响应填充到 <code>xmlHttp.responseText</code> 属性中。 </li>
		</ul>
		<p>其中的第一点，即就绪状态，将在下一篇文章中详细讨论，您将进一步了解 HTTP 请求的阶段，可能比您设想的还多。现在只要检查一个特定的值（4）就可以了（下一期文章中还有更多的值要介绍）。第二点，使用 <code>xmlHttp.responseText</code> 属性获得服务器的响应，这很简单。<font color="#996699">清单 6</font> 中的示例方法可供服务器根据 <a href="http://blog.csdn.net/baggio785/archive/2006/01/06/571779.aspx#code5"><font color="#996699">清单 5</font></a> 中发送的数据调用。</p>
		<p>
				<br />
				<a name="code6">
						<strong>清单 6. 处理服务器响应</strong>
				</a>
				<br />
		</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">function updatePage() {
  if (xmlHttp.readyState == 4) {
    var response = xmlHttp.responseText;
    document.getElementById("zipCode").value = response;
  }
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>这些代码同样既不难也不复杂。它等待服务器调用，如果是就绪状态，则使用服务器返回的值（这里是用户输入的城市和州的 ZIP 编码）设置另一个表单字段的值。于是包含 ZIP 编码的 <code>zipCode</code> 字段突然出现了，而用户<em>没有按任何按钮</em>！这就是前面所说的桌面应用程序的感觉。快速响应、动态感受等等，这些都只因为有了小小的一段 Ajax 代码。</p>
		<p>细心的读者可能注意到 <code>zipCode</code> 是一个普通的文本字段。一旦服务器返回 ZIP 编码，<code>updatePage()</code> 方法就用城市/州的 ZIP 编码设置那个字段的值，用户就可以改写该值。这样做有两个原因：保持例子简单，说明有时候可能<em>希望</em> 用户能够修改服务器返回的数据。要记住这两点，它们对于好的用户界面设计来说很重要。</p>
		<p>
				<br />
				<a name="IDAYKYW">
						<span class="atitle">
								<font size="4">连接 Web 表单</font>
						</span>
				</a>
		</p>
		<p>还有什么呢？实际上没有多少了。一个 JavaScript 方法捕捉用户输入表单的信息并将其发送到服务器，另一个 JavaScript 方法监听和处理响应，并在响应返回时设置字段的值。所有这些实际上都依赖于<em>调用</em> 第一个 JavaScript 方法，它启动了整个过程。最明显的办法是在 HTML 表单中增加一个按钮，但这是 2001 年的办法，您不这样认为吗？还是像 <font color="#996699">清单 7</font> 这样利用 JavaScript 技术吧。</p>
		<p>
				<br />
				<a name="code7">
						<strong>清单 7. 启动一个 Ajax 过程</strong>
				</a>
				<br />
		</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;form&gt;
 &lt;p&gt;City: &lt;input type="text" name="city" id="city" size="25" 
       <span class="boldcode"><strong>onChange="callServer();"</strong></span> /&gt;&lt;/p&gt;
 &lt;p&gt;State: &lt;input type="text" name="state" id="state" size="25" 
       <span class="boldcode"><strong>onChange="callServer();"</strong></span> /&gt;&lt;/p&gt;
 &lt;p&gt;Zip Code: &lt;input type="text" name="zipCode" id="city" size="5" /&gt;&lt;/p&gt;
&lt;/form&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>如果感觉这像是一段相当普通的代码，那就对了，正是如此！当用户在 city 或 state 字段中输入新的值时，<code>callServer()</code> 方法就被触发，于是 Ajax 开始运行了。有点儿明白怎么回事了吧？好，就是如此！</p>
		<p>
				<br />
				<a name="IDAYLYW">
						<span class="atitle">
								<font size="4">结束语</font>
						</span>
				</a>
		</p>
		<p>现在您可能已经准备开始编写第一个 Ajax 应用程序了，至少也希望认真读一下 <a href="http://blog.csdn.net/baggio785/archive/2006/01/06/571779.aspx#resources"><font color="#996699">参考资料</font></a> 中的那些文章了吧？但可以首先从这些应用程序如何工作的基本概念开始，对 <code>XMLHttpRequest</code> 对象有基本的了解。在下一期文章中，您将掌握这个对象，学会如何处理 JavaScript 和服务器的通信、如何使用 HTML 表单以及如何获得 DOM 句柄。</p>
		<p>现在先花点儿时间考虑考虑 Ajax 应用程序有多么强大。设想一下，当单击按钮、输入一个字段、从组合框中选择一个选项或者用鼠标在屏幕上拖动时，Web 表单能够立刻作出响应会是什么情形。想一想<em>异步</em> 究竟意味着什么，想一想 JavaScript 代码运行而且<em>不等待</em> 服务器对它的请求作出响应。会遇到什么样的问题？会进入什么样的领域？考虑到这种新的方法，编程的时候应如何改变表单的设计？</p>
		<p>如果在这些问题上花一点儿时间，与简单地剪切/粘贴某些代码到您根本不理解的应用程序中相比，收益会更多。在下一期文章中，我们将把这些概念付诸实践，详细介绍使应用程序按照这种方式工作所需要的代码。因此，现在先享受一下 Ajax 所带来的可能性吧。</p>
		<p>
				<br />
				<a name="resources">
						<span class="atitle">
								<font size="4">参考资料 </font>
						</span>
				</a>
		</p>
		<p>
				<strong>学习</strong>
				<br />
		</p>
		<ul>
				<li>您可以参阅本文在 developerWorks 全球站点上的 <a href="http://www.ibm.com/developerworks/xml/library/wa-ajaxintro1.html" target="_blank"><font color="#5c81a7">英文原文</font></a>。<br /><br /></li>
				<li>
						<a href="http://www.adaptivepath.com/" target="_blank">
								<font color="#5c81a7">Adaptive Path</font>
						</a>是一家领先的用户界面设计公司，仔细阅读他们的网站可以更多地了解 Ajax。 <br /><br /></li>
				<li>如果关心 Ajax 一词的来历，请看一看 <a href="http://adaptivepath.com/team/jjg.php" target="_blank"><font color="#5c81a7">Jesse James Garrett</font></a> 和他的 Ajax 文章（比如 <a href="http://adaptivepath.com/publications/essays/archives/000385.php" target="_blank"><font color="#5c81a7">这一篇</font></a>）。 <br /><br /></li>
				<li>可以先了解下一期文章的主题 <code>XMLHttpRequest</code> 对象，请阅读 <a href="http://www.jibbering.com/2002/4/httprequest.html" target="_blank"><font color="#5c81a7">关于 <code>XMLHttpRequest</code> 对象的这篇文章</font></a>。 <br /><br /></li>
				<li>如果使用 Internet Explorer，可以访问 <a href="http://msdn.microsoft.com/xml/" target="_blank"><font color="#5c81a7">Microsoft Developer Network 的 XML Developer Center</font></a>。 <br /><br /></li>
				<li>
						<a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax1/" target="_blank">
								<font color="#5c81a7">面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序</font>
						</a>（developerWorks，2005 年 9 月）介绍了这种革新方法，它解决了页面重新加载难题，可以创建动态的 Web 应用程序体验。 <br /><br /></li>
				<li>
						<a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax2/" target="_blank">
								<font color="#5c81a7">面向 Java 开发人员的 Ajax: Ajax 的 Java 对象序列化</font>
						</a>（developerWorks，2005 年 10 月）介绍了在 Ajax 应用程序中对数据进行序列化的五种方法。 <br /><br /></li>
				<li>
						<a href="http://www-128.ibm.com/developerworks/edu/os-dw-os-phpajax-i.html" target="_blank">
								<font color="#5c81a7">Using Ajax with PHP and Sajax</font>
						</a>（developerWorks，2005 年 10 月），这篇教程针对那些对开发丰富 Web 应用程序感兴趣的人，介绍了使用 Ajax 和 PHP 动态更新内容。 <br /><br /></li>
				<li>
						<a href="http://www-128.ibm.com/developerworks/webservices/library/ws-wsajax/" target="_blank">
								<font color="#5c81a7">Call SOAP Web services with AJAX, Part 1: Build the Web services client</font>
						</a>（developerWorks，2005 年 10 月）介绍了如何使用 Ajax 设计模式实现基于 Web 浏览器的 SOAP Web 服务客户机。 <br /><br /></li>
				<li>
						<a href="http://www.ibm.com/developerworks/cn/xml/x-matters41.html" target="_blank">
								<font color="#5c81a7">XML 问题: 超越 DOM</font>
						</a>（developerWorks，2005 年 5 月）详细阐述了如何使用文档对象模型来构建动态 Web 应用程序。 <br /><br /></li>
				<li>
						<a href="http://www.ibm.com/developerworks/edu/wa-dw-wa-ajax-i.html" target="_blank">
								<font color="#5c81a7">Build apps with Asynchronous JavaScript with XML, or AJAX</font>
						</a>（developerWorks，2005 年 11 月）演示了如何使用 Ajax 构造支持实时检验的 Web 应用程序。 <br /><br /></li>
				<li>
						<a href="http://www.ibm.com/developerworks/cn/java/j-ajax3/" target="_blank">
								<font color="#5c81a7">面向 Java 开发人员的 Ajax: 结合 Direct Web Remoting 使用 Ajax </font>
						</a>（developerWorks，2005 年 11 月）演示了如何实现 Ajax 的繁琐细节的自动化处理。 <br /><br /></li>
				<li>OSA Foundation 有一个 wiki <a href="http://wiki.osafoundation.org/bin/view/Projects/AjaxLibraries" target="_blank"><font color="#5c81a7">调查了 AJAX/JavaScript 库</font></a>。 <br /><br /></li>
				<li>XUL Planet 的 <a href="http://www.xulplanet.com/references/objref/XMLHttpRequest.html" target="_blank"><font color="#5c81a7">对象参考部分</font></a> 详细介绍了 XMLHttpRequest 对象（更不用说其他各种 XML 对象了，如 DOM、CSS、HTML、Web Service 以及 Windows 和 Navigation 对象）。 <br /><br /></li>
				<li>关于 AJax 的基本原理，请阅读 <a href="http://www.backbase.com/download/Whitepaper%20Backbase%20AJAX%20and%20Beyond.pdf" target="_blank"><font color="#5c81a7">策略白皮书</font></a>。 <br /><br /></li>
				<li>请看看 <a href="http://www.flickr.com/" target="_blank"><font color="#5c81a7">Flickr.com</font></a> 上展示的一些很棒的 Ajax 应用程序。 <br /><br /></li>
				<li>Google 的 <a href="http://gmail.google.com/" target="_blank"><font color="#5c81a7">GMail</font></a> 是另一个利用 Ajax 的革命性 Web 应用程序的例子。 <br /><br /></li>
				<li>
						<em>
								<a href="http://www.oreilly.com/catalog/headra/index.html" target="_blank">
										<font color="#5c81a7">Head Rush Ajax</font>
								</a>
						</em>（O'Reilly Media, Inc.，2006 年 2 月）包含了本文以及本系列文章所述的内容（还有更多），并采用了创新的获奖格式 Head First。 <br /><br /></li>
				<li>
						<em>
								<a href="http://www.oreilly.com/catalog/jscript4/index.html" target="_blank">
										<font color="#5c81a7">JavaScript: The Definitive Guide</font>
								</a>
						</em>，第 4 版（O'Reilly Media, Inc.，2001 年 11 月）是关于 JavaScript 语言和使用动态网页的好资料。 <br /><br /></li>
				<li>developerWorks <a href="http://www.ibm.com/developerworks/web/" target="_blank"><font color="#5c81a7">Web 体系结构专区</font></a> 专门发表关于各种基于 Web 的解决方案的文章。 <br /><br /></li>
		</ul>
		<p>
				<br />
				<strong>讨论</strong>
				<br />
		</p>
		<ul>
				<li>加入本文的<a href="javascript:void forumWindow()"><font color="#5c81a7">论坛</font></a> 。(您也可以通过点击文章顶部或者底部的论坛链接参加讨论。)<br /><br /></li>
				<li>
						<a href="http://weblogs.asp.net/mschwarz/" target="_blank">
								<font color="#5c81a7">Ajax.NET Professional</font>
						</a>是关于 Ajax 各个方面的很好的 blog。 <br /><br /></li>
				<li>通过参与 <a href="http://www.ibm.com/developerworks/blogs/" target="_blank"><font color="#5c81a7">developerWorks blog</font></a> 加入 developerWorks 社区。 </li>
		</ul>
		<br />
<img src ="http://www.blogjava.net/iKingQu/aggbug/36521.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iKingQu/" target="_blank">風向逆轉 - 就要爪哇</a> 2006-03-21 00:33 <a href="http://www.blogjava.net/iKingQu/articles/36521.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[收藏]Ajax简介(一)</title><link>http://www.blogjava.net/iKingQu/articles/36520.html</link><dc:creator>風向逆轉 - 就要爪哇</dc:creator><author>風向逆轉 - 就要爪哇</author><pubDate>Mon, 20 Mar 2006 16:29:00 GMT</pubDate><guid>http://www.blogjava.net/iKingQu/articles/36520.html</guid><wfw:comment>http://www.blogjava.net/iKingQu/comments/36520.html</wfw:comment><comments>http://www.blogjava.net/iKingQu/articles/36520.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/iKingQu/comments/commentRss/36520.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iKingQu/services/trackbacks/36520.html</trackback:ping><description><![CDATA[
		<p>　　作为J2EE开发人员，我们似乎经常关注“后端机制（backend mechanics）”。我们通常会忘记，J2EE的主要成功之处在Web应用程序方面；许多原因使得人们喜欢利用Web开发应用程序，但主要还是因为其易于部署的特点允许站点以尽可能低的成本拥有上百万的用户。遗憾的是，在过去几年中，我们在后端投入了太多的时间，而在使我们的Web用户界面对用户自然和响应灵敏方面却投入不足。</p>
		<p>　　本文介绍一种方法，Ajax，使用它可以构建更为动态和响应更灵敏的Web应用程序。该方法的关键在于对浏览器端的JavaScript、DHTML和与服务器异步通信的组合。本文也演示了启用这种方法是多么简单：利用一个Ajax框架（指DWR）构造一个应用程序，它直接从浏览器与后端服务进行通信。如果使用得当，这种强大的力量可以使应用程序更加自然和响应灵敏，从而提升用户的浏览体验。</p>
		<p>　　该应用程序中所使用的示例代码已打包为单独的WAR文件，可供下载。</p>
		<p>
				<strong>简介</strong>
		</p>
		<p>　　术语Ajax用来描述一组技术，它使浏览器可以为用户提供更为自然的浏览体验。在Ajax之前，Web站点强制用户进入提交/等待/重新显示范例，用户的动作总是与服务器的“思考时间”同步。Ajax提供与服务器异步通信的能力，从而使用户从请求/响应的循环中解脱出来。借助于Ajax，可以在用户单击按钮时，使用JavaScript和DHTML立即更新UI，并向服务器发出异步请求，以执行更新或查询数据库。当请求返回时，就可以使用JavaScript和CSS来相应地更新UI，而不是刷新整个页面。最重要的是，用户甚至不知道浏览器正在与服务器通信：Web站点看起来是即时响应的。</p>
		<p>　　虽然Ajax所需的基础架构已经出现了一段时间，但直到最近异步请求的真正威力才得到利用。能够拥有一个响应极其灵敏的Web站点确实激动人心，因为它最终允许开发人员和设计人员使用标准的HTML/CSS/JavaScript堆栈创建“桌面风格的（desktop-like）”可用性。</p>
		<p>　　通常，在J2EE中，开发人员过于关注服务和持久性层的开发，以至于用户界面的可用性已经落后。在一个典型的J2EE开发周期中，常常会听到这样的话，“我们没有可投入UI的时间”或“不能用HTML实现”。但是，以下Web站点证明，这些理由再也站不住脚了：</p>
		<ul>
				<li>
						<a href="http://backpackit.com/" target="_blank">BackPack</a>
				</li>
				<li>
						<a href="http://www.google.com/webhp?complete=1&amp;hl=en" target="_blank">Google Suggest</a>
				</li>
				<li>
						<a href="http://maps.google.com/" target="_blank">Google Maps</a>
				</li>
				<li>
						<a href="http://www.palmsphere.com/" target="_blank">PalmSphere</a>
				</li>
		</ul>
		<p>　　所有这些Web站点都告诉我们，Web应用程序不必完全依赖于从服务器重新载入页面来向用户呈现更改。一切似乎就在瞬间发生。简而言之，在涉及到用户界面的响应灵敏度时，基准设得更高了。</p>
		<p>
				<strong>定义Ajax</strong>
		</p>
		<p>　　Adaptive Path公司的Jesse James Garrett这样<a href="http://www.adaptivepath.com/publications/essays/archives/000385.php" target="_blank">定义Ajax</a>：</p>
		<p>　　Ajax不是一种技术。实际上，它由几种蓬勃发展的技术以新的强大方式组合而成。Ajax包含：</p>
		<ul>
				<li>基于<a href="http://www.w3.org/TR/xhtml1/" target="_blank">XHTML</a>和<a href="http://www.w3.org/Style/CSS/" target="_blank">CSS</a>标准的表示； 
</li>
				<li>使用<a href="http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/introduction.html" target="_blank">Document Object Model</a>进行动态显示和交互； 
</li>
				<li>使用XMLHttpRequest与服务器进行异步通信； 
</li>
				<li>使用JavaScript绑定一切。 </li>
		</ul>
		<p>　　这非常好，但为什么要以Ajax命名呢？其实术语Ajax是由Jesse James Garrett创造的，他说它是“Asynchronous JavaScript + XML的简写”。</p>
		<p>
				<strong>Ajax的工作原理</strong>
		</p>
		<p>　　Ajax的核心是JavaScript对象XmlHttpRequest。该对象在Internet Explorer 5中首次引入，它是一种支持异步请求的技术。简而言之，XmlHttpRequest使您可以使用JavaScript向服务器提出请求并处理响应，而不阻塞用户。</p>
		<p>　　在创建Web站点时，在客户端执行屏幕更新为用户提供了很大的灵活性。下面是使用Ajax可以完成的功能：</p>
		<ul>
				<li>动态更新购物车的物品总数，无需用户单击Update并等待服务器重新发送整个页面。 
</li>
				<li>提升站点的性能，这是通过减少从服务器下载的数据量而实现的。例如，在Amazon的购物车页面，当更新篮子中的一项物品的数量时，会重新载入整个页面，这必须下载32K的数据。如果使用Ajax计算新的总量，服务器只会返回新的总量值，因此所需的带宽仅为原来的百分之一。 
</li>
				<li>消除了每次用户输入时的页面刷新。例如，在Ajax中，如果用户在分页列表上单击Next，则服务器数据只刷新列表而不是整个页面。 
</li>
				<li>直接编辑表格数据，而不是要求用户导航到新的页面来编辑数据。对于Ajax，当用户单击Edit时，可以将静态表格刷新为内容可编辑的表格。用户单击Done之后，就可以发出一个Ajax请求来更新服务器，并刷新表格，使其包含静态、只读的数据。 </li>
		</ul>
		<p>　　一切皆有可能！但愿它能够激发您开始开发自己的基于Ajax的站点。然而，在开始之前，让我们介绍一个现有的Web站点，它遵循传统的提交/等待/重新显示的范例，我们还将讨论Ajax如何提升用户体验。</p>
		<p>
				<strong>Ajax可用于那些场景？——一个例子：MSN Money页面</strong>
		</p>
		<p>　　前几天，在浏览MSN Money页面的时候，有一篇<a href="http://moneycentral.msn.com/content/Investing/Realestate/P63633.asp" target="_blank">关于房地产投资的文章</a>引起了我的好奇心。我决定使用站点的“Rate this article”（评价本文）功能，鼓励其他的用户花一点时间来阅读这篇文章。在我单击vote按钮并等待了一会儿之后，整个页面被刷新，在原来投票问题所在的地方出现了一个漂亮的感谢画面。</p>
		<p>
				<img height="63" alt="" src="http://dev2dev.bea.com.cn/images/051101/0511010101.jpg" width="303" />
		</p>
		<p>　　而Ajax能够使用户的体验更加愉快，它可以提供响应更加灵敏的UI，并消除页面刷新所带来的闪烁。目前，由于要刷新整个页面，需要传送大量的数据，因为必须重新发送整个页面。如果使用Ajax，服务器可以返回一个包含了感谢信息的500字节的消息，而不是发送26,813字节的消息来刷新整个页面。即使使用的是高速Internet，传送26K和1/2K的差别也非常大。同样重要的是，只需要刷新与投票相关的一小节，而不是刷新整个屏幕。</p>
		<p>　　让我们利用Ajax实现自己的基本投票系统。</p>
		<p>
				<strong>原始的Ajax：直接使用XmlHttpRequest</strong>
		</p>
		<p>　　如上所述，Ajax的核心是JavaScript对象XmlHttpRequest。下面的示例文章评价系统将带您熟悉Ajax的底层基本知识：<a href="http://tearesolutions.com/ajax-demo/raw-ajax.html" target="_blank">http://tearesolutions.com/ajax-demo/raw-ajax.html</a>。注：如果您已经在本地WebLogic容器中安装了<a href="http://dev2dev.bea.com/2005/08/ajax-demo.war" target="_blank">ajax-demo.war</a>，可以导航到<a href="http://localhost:7001/ajax-demo/raw-ajax.html" target="_blank">http://localhost:7001/ajax-demo/raw-ajax.html</a>，</p>
		<p>　　浏览应用程序，参与投票，并亲眼看它如何运转。熟悉了该应用程序之后，继续阅读，进一步了解其工作原理细节。</p>　　首先，您拥有一些简单的定位点标记，它连接到一个JavaScriptcastVote(rank)函数。 <pre class="code">function castVote(rank) {
  var url = "/ajax-demo/static-article-ranking.html";
  var callback = processAjaxResponse;
  executeXhr(callback, url);
}
</pre><p>　　该函数为您想要与之通信的服务器资源创建一个URL并调用内部函数executeXhr，提供一个回调JavaScript函数，一旦服务器响应可用，该函数就被执行。由于我希望它运行在一个简单的Apache环境中，“cast vote URL”只是一个简单的HTML页面。在实际情况中，被调用的URL将记录票数并动态地呈现包含投票总数的响应。</p>　　下一步是发出一个XmlHttpRequest请求： <pre class="code">function executeXhr(callback, url) {
  // branch for native XMLHttpRequest object
  if (window.XMLHttpRequest) {
    req = new XMLHttpRequest();
    req.onreadystatechange = callback;
    req.open("GET", url, true);
    req.send(null);
  } // branch for IE/Windows ActiveX version
  else if (window.ActiveXObject) {
    req = new ActiveXObject("Microsoft.XMLHTTP");
    if (req) {
      req.onreadystatechange = callback;
      req.open("GET", url, true);
      req.send();
    }
  }
}

</pre><p>　　如您所见，执行一个XmlHttpRequest并不简单，但非常直观。和平常一样，在JavaScript领域，大部分的工作量都花在确保浏览器兼容方面。在这种情况下，首先要确定XmlHttpRequest是否可用。如果不能用，很可能要使用Internet Explorer，这样就要使用所提供的ActiveX实现。</p><p>executeXhr()方法中最关键的部分是这两行： </p><pre class="code">req.onreadystatechange = callback;
req.open("GET", url, true);
</pre><p>　　第一行定义了JavaScript回调函数，您希望一旦响应就绪它就自动执行，而req.open()方法中所指定的“true”标志说明您想要异步执行该请求。</p>　　一旦服务器处理完XmlHttpRequest并返回给浏览器，使用req.onreadystatechange指派所设置的回调方法将被自动调用。 <pre class="code">function processAjaxResponse() {
  // only if req shows "loaded"
  if (req.readyState == 4) {
    // only if "OK"
    if (req.status == 200) {
      502 502'votes').innerHTML = req.responseText;
    } else {
      alert("There was a problem retrieving the XML data:
" +
      req.statusText);
    }
  }
} 
</pre><p>　　该代码相当简洁，并且使用了几个幻数，这使得难以一下子看出发生了什么。为了弄清楚这一点，下面的表格（引用自<a href="http://developer.apple.com/internet/webcontent/xmlhttpreq.html" target="_blank">http://developer.apple.com/internet/webcontent/xmlhttpreq.html</a>）列举了常用的XmlHttpRequest对象属性。</p><table cellspacing="1" cellpadding="0" width="80%" bgcolor="#cccccc" border="0"><tbody><tr bgcolor="#ffffff"><td height="22"><p><strong>属性</strong></p></td><td><p><strong>描述</strong></p></td></tr><tr bgcolor="#ffffff"><td valign="top" height="22"><p>onreadystatechange</p></td><td valign="top"><p>每次状态改变所触发事件的事件处理程序</p></td></tr><tr bgcolor="#ffffff"><td valign="top" height="22"><p>readyState</p></td><td valign="top"><p>对象状态值： </p><ul><li>0 = 未初始化（uninitialized） 
</li><li>1 = 正在加载（loading） 
</li><li>2 = 加载完毕（loaded） 
</li><li>3 = 交互（interactive） 
</li><li>4 = 完成（complete） </li></ul></td></tr><tr bgcolor="#ffffff"><td valign="top" height="22"><p>responseText</p></td><td valign="top"><p>从服务器进程返回的数据的字符串形式</p></td></tr><tr bgcolor="#ffffff"><td valign="top" height="22"><p>responseXML</p></td><td valign="top"><p>从服务器进程返回的DOM兼容的文档数据对象</p></td></tr><tr bgcolor="#ffffff"><td valign="top" height="22"><p>status</p></td><td valign="top"><p>从服务器返回的数字代码，比如404（未找到）或200（就绪）</p></td></tr><tr bgcolor="#ffffff"><td valign="top" height="22"><p>statusText</p></td><td valign="top"><p>伴随状态码的字符串信息</p></td></tr></tbody></table><p>　　现在processVoteResponse()函数开始显示出其意义了。它首先检查XmlHttpRequest的整体状态以保证它已经完成（readyStatus == 4），然后根据服务器的设定询问请求状态。如果一切正常（status == 200）,就使用innerHTML属性重写DOM的“votes”节点的内容。</p><p>　　既然您亲眼看到了XmlHttpRequest对象是如何工作的，就让我们利用一个旨在简化JavaScript与Java应用程序之间的异步通信的框架来对具体的细节进行抽象。</p><p><strong>Ajax: DWR方式</strong></p><p>　　按照与文章评价系统相同的流程，我们将使用Direct Web Remoting（DWR）框架实现同样的功能。</p><p>　　假定文章和投票结果存储在一个数据库中，使用某种对象/关系映射技术来完成抽取工作。为了部署起来尽可能地简单，我们不会使用数据库进行持久性存储。此外，为使应用程序尽可能通用，也不使用Web框架。相反，应用程序将从一个静态HTML文件开始，可以认为它由服务器动态地呈现。除了这些简化措施，应用程序还应该使用Spring Framework关联一切，以便轻松看出如何在一个“真实的”应用程序中使用DWR。</p><p>　　现在应该下载示例应用程序并熟悉它。该应用程序被压缩为标准的WAR文件，因此您可以把它放置到任何一个Web容器中——无需进行配置。部署完毕之后，就可以导航到<a href="http://localhost:7001/ajax-demo/dwr-ajax.html" target="_blank">http://localhost:7001/ajax-demo/dwr-ajax.html</a>来运行程序。</p><p>　　可以查看<a href="http://dev2dev.bea.com/2005/08/source.html" target="_blank">HTML 源代码</a>，了解它如何工作。给人印象最深的是，代码如此简单——所有与服务器的交互都隐藏在JavaScript对象ajaxSampleSvc的后面。更加令人惊讶的是，ajaxSampleSvc服务不是由手工编写而是完全自动生成的！让我们继续，看看这是如何做到的。</p><p><strong>引入DWR</strong></p><p>　　如同在“原始的Ajax”一节所演示的那样，直接使用XmlHttpRequest创建异步请求非常麻烦。不仅JavaScript代码冗长，而且必须考虑服务器端为定位Ajax请求到适当的服务所需做的工作，并将结果封送到浏览器。</p><p>　　设计DWR的目的是要处理将Web页面安装到后端服务上所需的所有信息管道。它是一个Java框架，可以很轻松地将它插入到Web应用程序中，以便JavaScript代码可以调用服务器上的服务。它甚至直接与Spring Framework集成，从而允许用户直接向Web客户机公开bean。</p><p>　　DWR真正的巧妙之处是，在用户配置了要向客户机公开的服务之后，它使用反射来生成JavaScript对象，以便Web页面能够使用这些对象来访问该服务。然后Web页面只需接合到生成的JavaScript对象，就像它们是直接使用服务一样；DWR无缝地处理所有有关Ajax和请求定位的琐碎细节。</p><p>　　让我们仔细分析一下示例代码，弄清它是如何工作的。</p><p><strong>应用程序细节：DWR分析</strong></p><p>　　关于应用程序，首先要注意的是，它是一个标准的Java应用程序，使用分层架构（Layered Architecture）设计模式。使用DWR通过JavaScript公开一些服务并不影响您的设计。 </p><p><img height="344" alt="" src="http://dev2dev.bea.com.cn/images/051101/0511010102.jpg" width="209" /></p><p>　　下面是一个简单的Java服务，我们将使用DWR框架直接将其向JavaScript代码公开：</p><pre class="code">package com.tearesolutions.service;

public interface AjaxSampleSvc { 
  Article castVote(int rank);
}
</pre><p>　　这是一个被简化到几乎不可能的程度的例子，其中只有一篇文章可以投票。该服务由Spring管理，它使用的bean名是ajaxSampleSvc，它的持久性需求则依赖于ArticleDao。详情请参见applicationContext.xml。</p><p>　　为了把该服务公开为JavaScript对象，需要配置DWR，添加dwr.xml文件到WEB-INF目录下： </p><pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE dwr PUBLIC
 "-//GetAhead Limited//DTD Direct Web Remoting 0.4//EN"
 "http://www.getahead.ltd.uk/dwr/dwr.dtd"&gt;
	
&lt;dwr&gt;
 &lt;allow&gt;
  &lt;create creator="spring" javascript="ajaxSampleSvc"&gt;
   &lt;param name="beanName" value="ajaxSampleSvc" /&gt;
  &lt;/create&gt;
  &lt;convert converter="bean" match="com.tearesolutions.model.Article"/&gt;
  &lt;exclude method="toString"/&gt;
  &lt;exclude method="setArticleDao"/&gt;
 &lt;/allow&gt;
&lt;/dwr&gt;
</pre><p>　　dwr.xml文件告诉DWR哪些服务是要直接向JavaScript代码公开的。注意，已经要求公开Spring bean ajaxSampleSvc。DWR将自动找到由应用程序设置的SpringApplicationContext。为此，必须使用标准的servlet过滤器ContextLoaderListener来初始化Spring ApplicationContext。</p>　　DWR被设置为一个servlet，所以把它的定义添加到web.xml： <pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD 
 Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;

&lt;web-app&gt;
 &lt;display-name&gt;Ajax Examples&lt;/display-name&gt;

 &lt;listener&gt;
  &lt;listener-class&gt;
      org.springframework.web.context.ContextLoaderListener
  &lt;/listener-class&gt;
 &lt;/listener&gt;
	
 &lt;servlet&gt;
  &lt;servlet-name&gt;ajax_sample&lt;/servlet-name&gt;
  &lt;servlet-class&gt;com.tearesolutions.web.AjaxSampleServlet&lt;/servlet-class&gt;
  &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
 &lt;/servlet&gt;

 &lt;servlet&gt;
  &lt;servlet-name&gt;dwr-invoker&lt;/servlet-name&gt;
  &lt;display-name&gt;DWR Servlet&lt;/display-name&gt;
  &lt;description&gt;Direct Web Remoter Servlet&lt;/description&gt;
  &lt;servlet-class&gt;uk.ltd.getahead.dwr.DWRServlet&lt;/servlet-class&gt;
  &lt;init-param&gt;
   &lt;param-name&gt;debug&lt;/param-name&gt;
   &lt;param-value&gt;true&lt;/param-value&gt;
  &lt;/init-param&gt;
 &lt;/servlet&gt;

 &lt;servlet-mapping&gt;
  &lt;servlet-name&gt;ajax_sample&lt;/servlet-name&gt;
  &lt;url-pattern&gt;/ajax_sample&lt;/url-pattern&gt;
 &lt;/servlet-mapping&gt;

 &lt;servlet-mapping&gt;
  &lt;servlet-name&gt;dwr-invoker&lt;/servlet-name&gt;
  &lt;url-pattern&gt;/dwr/*&lt;/url-pattern&gt;
 &lt;/servlet-mapping&gt;
&lt;/web-app&gt;
</pre><p>　　做完这些之后，可以加载<a href="http://localhost:7001/ajax-demo/dwr" target="_blank">http://localhost:7001/ajax-demo/dwr</a>，看看哪些服务可用。结果如下：</p><p><img height="102" alt="" src="http://dev2dev.bea.com.cn/images/051101/0511010103.jpg" width="305" /></p><p>图3. 可用的服务</p>　　单击ajaxSampleSvc链接，查看有关如何在HTML页面内直接使用服务的示例实现。其中包含的两个JavaScript文件完成了大部分的功能： <pre class="code">&lt;script type='text/javascript' 
   src='/ajax-demo/dwr/interface/ajaxSampleSvc.js'&gt;&lt;/script&gt;
&lt;script type='text/javascript' 
   src='/ajax-demo/dwr/engine.js'&gt;&lt;/script&gt;
</pre><p>ajaxSampleSvc.js是动态生成的：</p><pre class="code">function ajaxSampleSvc() { }

ajaxSampleSvc.castVote = function(callback, p0)
{ 
  DWREngine._execute(callback, '/ajax-demo/dwr', 
 'ajaxSampleSvc', 'castVote', p0);
}
</pre><p>　　现在可以使用JavaScript对象ajaxSampleSvc替换所有的XmlHttpRequest代码，从而重构raw-ajax.html文件。可以在dwr-ajax.html文件中看到改动的结果；下面是新的JavaScript函数：</p><pre class="code">function castVote(rank) {
  ajaxSampleSvc.castVote(processResponse, rank);
}
function processResponse(data) {
 var voteText = "<p><strong>Thanks for Voting!</strong></p>"
    + "<p>Current ranking: " + data.voteAverage 
    + " out of 5</p>" 
    + "<p>Number of votes placed: " 
    + data.numberOfVotes + "</p>";
 502 502'votes').innerHTML = voteText;       
}
</pre><p>　　惊人地简单，不是吗？由ajaxSampleSvc对象返回的Article域对象序列化为一个JavaScript对象，允许在它上面调用诸如numberOfVotes()和voteAverage()之类的方法。在动态生成并插入到DIV元素“votes”中的HTML代码内使用这些数据。</p><p><strong>下一步工作</strong></p><p>　　　在后续文章中，我将继续有关Ajax的话题，涉及下面这些方面：</p><ul><li>Ajax最佳实践 </li></ul><p>　　像许多技术一样，Ajax是一把双刃剑。对于一些用例，其应用程序其实没有必要使用Ajax，使用了反而有损可用性。我将介绍一些不适合使用的模式，突出说明Ajax的一些消极方面，并展示一些有助于缓和这些消极方面的机制。例如，对<a href="http://www.netflix.com/BrowseSelection" target="_blank">Netflix电影浏览器</a>来说，Ajax是合适的解决方案吗？或者，如何提示用户确实出了一些问题，而再次单击按钮也无济于事？</p><ul><li>管理跨请求的状态 </li></ul><p>　　在使用Ajax时，最初的文档DOM会发生一些变化，并且有大量的页面状态信息存储在客户端变量中。当用户跟踪一个链接到应用程序中的另一个页面时，状态就丢失了。当用户按照惯例单击Back按钮时，呈现给他们的是缓存中的初始页面。这会使用户感到非常迷惑！</p><ul><li>调试技巧 </li></ul><p>　　使用JavaScript在客户端执行更多的工作时，如果事情不按预期方式进行，就需要一些调试工具来帮助弄清出现了什么问题。</p><p><strong>结束语</strong></p><p>　　本文介绍了Ajax方法，并展示了如何使用它来创建一个动态且响应灵敏的Web应用程序。通过使用DWR框架，可以轻松地把Ajax融合到站点中，而无需担心所有必须执行的实际管道工作。</p><p>　　特别感谢Getahead IT咨询公司的Joe Walker和他的团队开发出DWR这样神奇的工具。感谢你们与世界共享它！</p><p><strong>下载</strong></p><p>　　本文中演示的应用程序源代码可供下载：<a href="http://dev2dev.bea.com/2005/08/ajax-demo.war" target="_blank">ajax-demo.war</a>（1.52 MB）。</p><img src ="http://www.blogjava.net/iKingQu/aggbug/36520.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iKingQu/" target="_blank">風向逆轉 - 就要爪哇</a> 2006-03-21 00:29 <a href="http://www.blogjava.net/iKingQu/articles/36520.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>