270 likes | 487 Views
Ajax 编程技术 第三章 Ajax 和服务器端技术. 3.1 概述. 如果只使用 XMLHttpRequest 更新页面,而不使用任何来自服务器输入的技术,不能称之为 Ajax 。 使用 Ajax 的最大优势之一就是,可以为 Ajax 应用程序选择自己偏爱的服务器端技术,如 ASP.NET, PHP, Java 等。 对于每种服务器端技术来说, Ajax 读取 XMLHttpRequest 对象与服务器通信的方式基本上是相同的,但服务器接收到信息后的处理方式就个不相同了。. 3.2 Ajax 和服务器端技术. 表单和 HTML 控件
E N D
3.1 概述 如果只使用XMLHttpRequest更新页面,而不使用任何来自服务器输入的技术,不能称之为Ajax。 使用Ajax的最大优势之一就是,可以为Ajax应用程序选择自己偏爱的服务器端技术,如ASP.NET, PHP, Java 等。 对于每种服务器端技术来说,Ajax 读取XMLHttpRequest 对象与服务器通信的方式基本上是相同的,但服务器接收到信息后的处理方式就个不相同了。 3-2
3.2 Ajax和服务器端技术 • 表单和HTML控件 Ajax并未改变HTML控件的工作方式和从其获得数据的方式,服务器也采用以往的方式来接收它们。但是有两个问题: • 调用服务器端页面的方式; • HTML表单完全从页面中删除或修改后,不能按预期方式工作。我们分别解释。 3-3
Response.php Request.php 服务器 返回数据 <form> </form> 服务器 进行处理 用户单击按钮 提交数据 服务器 返回数据 Button 浏览器显示的原始页面 提交后浏览器重新定向的页面 3.2 Ajax和服务器端技术 • 传统的表单的提交模型 提交表单的做法通常是建立一个带有按钮的表但,用户输入完数据后单击按钮后,就将此表单提交给服务器。 传统的ASP和PHP使用表单的ACTION属性将用户从原始页面重定向到响应页面。该处理是在用户被重定向新页面之前在服务器上完成,新页面用来显示相应的响应数据。 3-4
3.2 Ajax和服务器端技术 在Ajax之前,我们使用的都是这种传统的提交、重定向模式;而Ajax提出了使用脚本提交页面的思想。 • Ajax/JavaScript提交模型 Ajax使用的JavaScript提交模型在以前传统的提交模型基础上进行了变化。在此模型中,表单可以可选地从模型中删除。 这种新的模型使用JavaScript截取事件调用,当该事件发生时(如用户单击提交按钮),提交的数据传递给对应的脚本,然后有脚本发起对服务器的调用。 脚本甚至不必马上提交数据,可以继续等待其它条件也满足后再提交数据。 在该模型中,因为脚本可以立即响应事件且不必等待数据的提交,所以从服务器返回的数据也不必马上显示给用户,而脚本也不必像以前一样被动等待服务器的响应。 3-5
Response.php 服务器端 进行处理 事件发生 脚本到 服务器 服务器返回数据 3.2 Ajax和服务器端技术 Default.htm <form onEbent…> Jscript.js 部分页 面更新 浏览器显示的页面 3-6
3.3 服务器端的情况 javaScript用来启用客户机/服务器之间的交互。C/S中的服务器端会接收来自HTTP请求的数据,然后处理数据,再以服务器响应所采用的格式返回数据。 • 向服务器提交数据 Ajax使用XMLHttpRequest对象向服务器提交数据,这一过程分三个步骤: • 设置事件在接收数据时触发; • 随请求一起调用open方法; • 发送请求。 3-7
3.3 服务器端的情况 • 提交使用格式 XMLHttpRequest.opwn(method, URLto call, asynchronous or synchronous); 其中Method:有两种方式,GET、POST: • 用GET方式: XMLHttpRequest.open(“GET”, “Reponse.php&value=1”, “true”); xHRObject.send(null); • 用POST方式: var argument = “value=“; argument += encodeURIComponent(data) XMLHttpRequest.open(“POST”, “Reponse.php”, “true”); xHRObject.send(argument); 3-8
3.3 服务器端的情况 • 服务器接收请求 JavaScript使用XMLHttpRequest对象的POST或GET方法,将数据封装到URL或Request中,向服务器提交数据。 • 在PHP中,可以使用$_GET、$_POST、$_REQUEST收集客户机传上来的数据。 • 在ASP、ASP.NET中,可以使用QueryString、Form或Params收集客户机传上来的数据。 • 从HTML表单接收数据和从源自JavaScript的请求接收数据没有差别。 • 服务器获得数据后,就可以按照自己的方式进行处理,然后将处理结果返回给客户端。 3-9
3.4 编写HTTP响应 与传统的服务器端技术所使用的事件顺序不同,在Ajax 中,用户要显示的信息无法立即写到页面中。取而代之的是,必须将信息封装在HTTP响应中。办法很简单: • 在PHP中,可以使用echo 命令: $data = “This is our data.”; echo $data; • 在ASP或ASP.NET中,可以Response.Write方法: string data = “This is our data.”; Response.Write(data); 3-10
3.4 编写HTTP响应 我们可以创建更为复杂的结构(如XML结构)。前提是,只要能将它们解析为文本即可。在PHP中,以下代码就是一个示例: $doc = new domDocument(‘1.0’); $root = $doc->createElement(‘root’); $root = $doc->appendChild($root); $child = $doc->createElement(‘child’); $child = $root->appendChild($child); $value = $doc->createTextNode(“Data”); $value = $child->appendChild($value); $strXml = $doc->saveXML(); echo $strXml; 最后生成的XML文档结果如下: <?xml version=“1.0”?> <root> <child>Data</child> </root> 相应的字符串追加在HTTP响应之后,然后回传给客户端显示。 3-11
3.4 编写HTTP响应 • XMLHttpRequest对象 XMLHttpRequest对象并不是Ajax技术用来执行客户机/服务器交互的唯一方法。但它是最受欢迎的一种方法。 我们不讨论该对象的工作原理,只介绍它的工作步骤: • 回调函数:接收数据的第一阶段称为回调。这只是一个JavaScript函数,在数据完成从服务器的下载时运行。命名回调函数时,可以起一个类似getData()的名称。回调函数在大多数Ajax应用程序中的作用都类似。 3-12
3.4 编写HTTP响应 在回调函数中,第一个要执行的任务是检查数据是否已下载完毕,这可以通过检查XMLHttpRequest对象的readyState属性是否等于4(代表已完成下载)来实现。回调函数的典型形式如下: function getData() { if (xHRObject.readyState==4) { // do some processing } } 确定数据已下载完毕后,可以用XMLHttpRequest对象以下两种属性之一来取回数据: • responseText • responseXML 3-13
3.4 编写HTTP响应 • responseText属性 responseText属性是从HTTP响应中重新取回数据的最常见、最简单的方法。可以创建一个新的JavaScript 变量来收集该响应的内容。 例如,在服务器端的PHP代码中,我们已经准备了回传信息: $data = “This is our data.”; 可以使用responseText属性来重新取回HTML/XHTML中的数据。 function myReturnMethod() { if (xmlhttp.readyState==4) { if (xmlhttp.status == 200) alert(xmlhttp.responseText); else if(xmlhttp.status == 404) alert("Requested file not found"); else alert("Error has occurred with status code:"+xmlhttp.status); } } 3-14
3.4 编写HTTP响应 如果要重新取回XML中的数据,而仍使用responseText属性,应将XML数据作为字符串返回: $data = “<?xml version=\”1.0\” encoding=\”ISO-8859-1\” standalone = \”yes\”?><root><child>Data</child></root>”; echo $data; 3-15
3.4 编写HTTP响应 • responseXML属性 如果想要将XML文档回传给客户端,responseXML属性是一个不错的选择。它将响应视作XML文档对象,然后用DMO迭代不同的元素、属性和文本节点。 但是,使用此属性时会存在一些问题。假定我们使用以下服务器端代码读取XML文档: $data = “<?xml version=\”1.0\” encoding=\”ISO-8859-1\” standalone = \”yes\”?><root><child>Data</child></root>”; echo $data; 然后,将用来读取的JavaScript代码更改为: var document = xHRObject.responseXML; 它有可能没法取回完整的XML文档,有可能是空的,并没有传输的XML标记。这是因为编写响应之前,必须要将响应的ContentType设置为text/xml。 3-16
3.4 编写HTTP响应 遗憾是的IE浏览器不允许这样的设置。必须在服务器上进行此项设置,客户端才能正常使用responseXML属性。 在Firefox中,可以在JavaScript中使用overrideMimeType方法将类型设置为text/xml类型: xHRObject.overrideMimeType(“text/xml”); xHRObject.send(null); var document = xHRObject.responseXML; 此属性在IE浏览器中没有。但问题还不止这些,如果XML文档中有错误导致格式有问题,就会从IE中得到一个空的对象,而且不会马上看到明显的错误消息。 3-17
3.4 编写HTTP响应 • 调式responseXML 在调查为何从responseXML中得到返回内容时,可以使用4种方法。常见的方法是检查responseXML中是否有返回内容。例如: var text = xHRObject.responseXML; Alert(text); 我们会指望得到类似的内容: <?xml version=“1.0” encoding=“ISO-8859-1” Standalone=“yes”?><root><child>Data</child></root> 如果没有得到类似内容,说明响应就没有服务器的正确传输,此时需要检查服务器端的代码。 3-18
3.4 编写HTTP响应 • 在IE中调式responseXML 如果要了解IE中有关某一错误的详细信息,可用如下代码返回一个错误消息: var errorcode = xHRObject.responseXML.parseError.errorCode; 一般情况下,IE返回值是0,但如果已将ContentType设置成 text/xml,并且responseXML.xml 为空,则IE返回值为0以外的数字。 我们还可以用如下代码得到更为详细的错误信息: var errorcode = xHRObject.responseXML.parseError.reason; 3-19
3.4 编写HTTP响应 • 使用数据 从responseXML属性中成功返回数据后,可以把它当作DOM对象从中重新取回数据。例如,假设从responseXML属性中成功返回的数据是: <?xml version=“1.0” encoding=“ISO-8859-1” standalone=“yes”?> <cart> <bood> <title>Beginning PHP with Ajax</title> <quantity>1</quantity> </book> </cart> 3-20
3.4 编写HTTP响应 我们可以用如下代码返回XML文档中的<book>元素: var XMLDoc = xHRObject.responseXML; var book = XMLDoc.getElementsByTagName(“book”); 还可以使用以下代码导航到book中的第一个元素: var title = book[0].firstChild; 注意,从XML文档中返回文档内容的方式,不同的浏览器是不同的。 • IE使用text属性获得: var title = book[0].firstChild.text; //返回“Beginning PHP with Ajax” • Mozilla使用textContent属性获得: var title = book[1].firstChild.textContent; //返回“Beginning PHP with Ajax” 3-21
3.4 编写HTTP响应 上例中,要强调的是,IE中的book[0]是第一个节点信息,而Firefox则是book[1]! Firefox中的book[0]会包含一个带有换行字符的文本节点,因为Firefox不会跳过空白字符,而将它们视为单独的节点,IE不会这样。 3-22
3.5 服务器端技术 到目前为止,我们讨论的只是数据发送和接收的过程,没有谈论服务器本身。对于Ajax来说,服务器端技术是独立的一块,与服务器端语言相关,必须单独讨论。我们在此以PHP技术为例来讨论。 • 使用Ajax与PHP的示例 • 假设有个MySql数据库myDataBase,其中一张表users有如下信息: 3-23
3.5 服务器端技术 • 编写一网页,其中用下拉菜单显示用户姓名,选定某一用户名(图1),页面从服务器处得到该用户的姓名和email地址,并在本页面显示这些信息(图2)。 图1 图2 3-24
3.5 服务器端技术 • firstPage.htm: <html> <head> <script src="responsexml.js"></script> </head> <body> <form> Select a User: <select name="users" onchange="showUser(this.value)"> <option value="1">李文</option> <option value="2">郭欣</option> <option value="3">贺琪</option> <option value="4">郭靖</option> </select> </form> <table border=0 cellpadding=10 cellspacing=0 style="font-size:10pt;"> <tr><td id="name"></td><td id="email"></td></tr> </table> </body> </html> 3-25
3.5 服务器端技术 • responsexml.php <?php header('Content-Type: text/xml'); header("Cache-Control: no-cache, must-revalidate"); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); $q=$_GET["q"]; $cn=@mysql_connect('localhost',‘user',‘password') or die("不能连接数据库"); $strsql="select * from users where regid='".$q."'order by regid"; $result=mysql_db_query(‘myDataBase',$strsql,$cn); echo '<?xml version="1.0" encoding="gb2312"?><person>'; while($row = mysql_fetch_array($result)) { echo "<name>" . $row['name'] . "</name>"; echo "<email>" . $row['email_address'] . "</email>"; } echo "</person>"; mysql_close($cn); ?> 3-26
3.5 服务器端技术 • responsexml.js var xmlHttp function showUser(str) { xmlHttp=GetXmlHttpObject() if (xmlHttp==null) { alert ("Browser does not support HTTP Request") return } var url="responsexml.php" url=url+"?q="+str url=url+"&sid="+Math.random() xmlHttp.onreadystatechange=stateChanged xmlHttp.open("GET",url,true) xmlHttp.send(null) } function stateChanged() { if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete") { xmlDoc=xmlHttp.responseXML; var nameText = ""; var emailText = ""; var nameNode = xmlDoc.getElementsByTagName('name'); for (i=0; i<nameNode.length; i++) { var name = nameNode[i]; var nameValue = name.firstChild.nodeValue; nameText += nameValue+"<br>"; var emailNode = xmlDoc.getElementsByTagName('email'); var email = emailNode[i]; var emailValue = email.firstChild.nodeValue; emailText += emailValue + "<BR>"; } document.getElementById("name").innerHTML = nameText; document.getElementById("email").innerHTML = emailText; } } function GetXmlHttpObject() { var objXMLHttp=null if (window.XMLHttpRequest) { objXMLHttp=new XMLHttpRequest() } else if (window.ActiveXObject) { objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP") } return objXMLHttp } 3-27