AJAX技术

  • 一、理解AJAX
  • 1.1 AJAX是什么?
  • 1.2 AJAX主要实现什么功能
  • 1.3 AJAX相关的技术
  • 1.3.1 XML与XSL
  • 1.3.2 XMLHttpRequest
  • 二、XMLHttpRequest 对象
  • 2.1 创建XMLHttpRequest对象
  • 2.2 XMLHttpRequest 的属性
  • 2.3 XMLRequest 的方法
  • 2.4 一个简单的示例
  • 2.5 AJAX 的交互模式
  • 2.6 使用 innerHTML 属性创建动态内容
  • 三、DOM 和JavaScript
  • 3.1 DOM的概念
  • 3.2 DOM 与 JavaScript
  • 3.3 使用DOM动态编辑页面
  • 四、AJAX的常用应用
  • 4.1 AJAX适用场景
  • 4.2 AJAX不适用场景


一、理解AJAX

1.1 AJAX是什么?

AJAX是英文Asynchronous JavaScript and XML 的缩写,含义是异步JavaScript与XML。

1.2 AJAX主要实现什么功能

该技术主要实现客户与服务器的异步通信实现页面的部分刷新。AJAX可以在不刷新整个页面的情况下用JavaScript操作DOM以实现页面动态更新。

1.3 AJAX相关的技术

1.3.1 XML与XSL

XML(eXtendsible Markup Language):可扩展的标记语言

  • XML 指可扩展标记语言(EXtensible Markup Language)
  • XML 是一种标记语言,很类似 HTML
  • XML 的设计宗旨是传输数据,而非显示数据
  • XML 标签没有被预定义。您需要自行定义标签。
  • XML 被设计为具有自我描述性。
  • XML 是 W3C 的推荐标准
  1. 没有任何行为的 XML , XML 是不作为的。
    也许这有点难以理解,但是 XML 不会做任何事情。XML 被设计用来结构化、存储以及传输信息。

下面是 John 写给 George 的便签,存储为 XML:

<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>

上面的这条便签具有自我描述性。它拥有标题以及留言,同时包含了发送者和接受者的信息。

但是,这个 XML 文档仍然没有做任何事情。它仅仅是包装在 XML 标签中的纯粹的信息。我们需要编写软件或者程序,才能传送、接收和显示出这个文档。

  1. XML 仅仅是纯文本
  2. XML 不是对 HTML 的替代
    XML 是对 HTML 的补充。
    XML 不会替代 HTML,理解这一点很重要。在大多数 web 应用程 序中,XML 用于传输数据,而 HTML 用于格式化并显示数据。
    对 XML 最好的描述是:
    XML 是独立于软件和硬件的信息传输工具。

XSL(eXtendsible Stylesheet Language):可扩展的样式单语言,它是一种用来转换XML文档结构的语言。使用XSL可以从一个XML文档中提取数据,并使用该信息创建另一个XML文档。

1.3.2 XMLHttpRequest

XMLHttpRequest是浏览器中定义的对象,它是AJAX技术中的核心对象。	通过JavaScript脚本可以创建XMLHttpRequest 对象。XMLHttpRequest 对象定义了若干属性和方法,通过这些方法和属性就可以向服务器发出异步请求和处理响应结果。

二、XMLHttpRequest 对象

2.1 创建XMLHttpRequest对象

var xmlHttp;
function createXMLHttpRequest(){
	if(window.XMLHttpRequest){
	    //  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
		xmlHttp = new XMLHttpRequest();
	}else{
	 	// IE6, IE5 浏览器执行代码
		xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
	}
}

2.2 XMLHttpRequest 的属性

属性名

说明

onreadystatechange

为异步请求设置事件处理程序。每当XMLHttpRequest对象的状态改变时都会触发这个事件处理器,通常会调用一个JavaScript函数

readState

该属性表示请求的状态。它可以有下面几个不同的值:0:未初始化;1:正在加载;2:已加载;3:交互中;4:完成

responseText

检索服务器响应,并表示为文本

responseXML

检索服务器响应,并表示为XML DOM对象

status

检索服务器的HTTP状态码。如404 表示Not Found,200表示OK

statusText

检索服务器的HTTP状态码的文本;

responseBody

检索响应体。该属性是IE7及以后版本的window对象,但不是W3C的规范

2.3 XMLRequest 的方法

方法名

说明

abort()

取消当前HTTP请求

getAllResponseHeaders()

返回所有的请求头。如果 readyState 属性的值不是 3或4,将返回 null。

getResponseHeader()

返回指定的响应头。如果 readyState 属性的值不是 3或4,将返回 null。

open(method,url,async)

规定请求的类型、URL 以及是否异步处理请求。method:请求的类型;GET 或 POST ;url:文件在服务器上的位置;async:true(异步)或 false(同步)

send()

发送 HTTP 请求,使用传递给 open() 方法的参数,以及传递给该方法的可选请求体。

setRequestHeader()

向一个打开但未发送的请求设置或添加一个 HTTP 请求。

2.4 一个简单的示例

simpleRequest.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Simple XMLHttpRequest</title>
    <script type="text/javascript">
        var xmlHttp;
        function createXMLHttpRequest() {
            if (window.XMLHttpRequest) {
                xmlHttp = new XMLHttpRequest();
            }
            else
            {
                xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
        }

        function startRequest() {
            createXMLHttpRequest();
            xmlHttp.onreadystatechange = handleStateChange;
            xmlHttp.open("GET", "simpleResponse.xml", "true");
            xmlHttp.send(null);
        }

        function handleStateChange() {
            if (xmlHttp.readyState == 4) {
                if (xmlHttp.status == 200) {
                    alert("服务器返回:" + xmlHttp.responseText);
                }
            }
        }
    </script>
</head>
<body>
<form action="#">
    <input type="button" value="开始异步请求" onclick="startRequest();"/>
</form>
</body>
</html>

simpleResponse.xml

Hello from the server!

2.5 AJAX 的交互模式

java 模拟ajax请求 javaweb ajax_服务器

  1. 客户触发事件
<input type="button" value="开始异步请求" 
    onclick="startRequest();"/>

这里,当用户点击按钮时,将触发onclick事件,程序调用startRequest()函数。

  1. 创建XMLHttpRequest 对象

在startReques()函数中调用createXMLHttpRequest()函数创建了XMLHttpRequest对象

var xmlHttp;
function createXMLHttpRequest() {
   if(window.XMLHttpRequest) {
       xmlHttp = new XMLHttpRequest();
   }
   else{
       xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
   }
}
  1. 向服务器发出请求

在向服务器发出请求之前,应该通过XMLHttpRequest 对象的 onreadystatechange 属性设置回调函数。当XMLHttpRequest 对象的内部状态改变时就会调用回调函数,因此回调函数是处理响应的地方。

function startRequest() {
	createXMLHttpRequest();
	xmlHttp.onreadystatechange = handleStateChange;
	xmlHttp.open("GET", "simpleResponse.xml", "true");//打开一个HTTP请求,请求的HTTP方法为GET,请求的资源是simpleResponse.xml,并且为异步请求
	xmlHttp.send(null);
}

接下来调用XMLHttpRequest 对象的open() 打开一个HTTP请求,在该方法中需要指定请求的HTTP方法(GET方法或者POST方法)以及请求的资源。请求的资源可以是动态资源,如Servlet、CGI脚本或者任何服务器技术等。
调用XMLHttpRequest 对象的**send()**将请求发送到指定的目标资源,send()接受一个参数,通常是一个字符串或DOM对象。这个参数作为请求体的一部分发送到目标URL。当向send()提供参数时,要确保open()中指定的HTTP方法为POST。如果使用POST方法,则需要设置XMLHttpRequest 对象的Content-Type首部,如下所示:

xmlHttp.setRequestHeader("Conetnt-Type","application/x-www-form-urllencoded");
//如果需要像 HTML 表单那样 POST 数据,请使用 setRequestHeader() 来添加 HTTP 头。

如果没有数据作为请求体的一部分发送,该参数应指定为null。

  1. 服务器处理请求并返回响应

如果请求的是静态资源,服务器将返回该资源。如果请求的是动态资源,服务器将执行动态资源,这可能需要访问数据库甚至另一个系统,然后向用户返回响应。
XMLHttpRequest对象提供两个访问服务器响应的属性。一个属性是responseText,它将响应提供一个字符串。另一个属性是responseXML,它将响应提供为一个XML对象。

//使用responseText属性来访问服务器响应
function handleStateChange() {
   if (xmlHttp.readyState == 4) {
      if (xmlHttp.status == 200) {
         alert("服务器返回:" + xmlHttp.responseText);
      }
   }
}

由于XMLHttpRequest 对象只能处理text/html类型的结果,所以如果请求的是动态资源(如Servlet),需要将Content-Type响应头设置为text/xml,另外,为了避免浏览器在本地缓存结果,需将Cache-Control响应头设置为 no-cache,如下所示:

response.setHeader("Cache-Control","no-cache");
  1. 通过回调函数处理结果

通过 回调函数可以对响应结果进行处理。在回调函数中首先应该检查XMLHttpRequest 对象的redyState 属性和status 属性的值。当readyState 属性值为4、status 属性的值为200 时表示响应完成,这时才能使用XMLHttpRequest 对象的responseText 或 response XML 检索请求结果。

//回调函数
function handleStateChange() {
   if (xmlHttp.readyState == 4) {
      if (xmlHttp.status == 200) {
         alert("服务器返回:" + xmlHttp.responseText);
      }
   }
}
  1. 更新HTML DOM 对象

客户使用新的数据更新HTML DOM 页面表示元素。JavaScript脚本可以使用DOM API 获得 HTML 的每个元素的引用。一般方法是使用document.getElementById(“userIdMessage”),这里,userIdMessage 是HTML 文档的一个元素的id属性值。有了元素的引用,JavaScript就可以修改元素的属性、修改元素的style属性或者添加、删除、修改子元素。修改元素内容的一个常用方法是设置元素的innerHTML 属性值

2.6 使用 innerHTML 属性创建动态内容

innerHTML 属性是一个简单的字符串,表示一组开始标签和结束标签之间的内容。

  • 举例:
    innerHTML.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>学生查询</title>
    <script type="text/javascript">
        var xmlHttp;
        function createXMLHttpRequest() {
            if (window.XMLHttpRequest) {
                xmlHttp = new XMLHttpRequest();
            }
            else {
                xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
        }
        function startRequest() {
            createXMLHttpRequest();
            xmlHttp.onreadystatechange = handleStateChange;
            xmlHttp.open("GET", "innerHTML.xml", "true");
            xmlHttp.send(null);
        }
        function handleStateChange() {
            if (xmlHttp.readyState == 4) {
                if (xmlHttp.status == 200) {
                    document.getElementById("results").innerHTML = xmlHttp.responseText;
                }
            }
        }
    </script>
</head>
<body>
<form action="#">
    <input type="button" value="查询学生" onclick="startRequest();"/>
    <div id="results"></div>
</form>
</body>
</html>

innerHTML.xml

<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<table border="1">
    <tbody>
        <tr><td>学号</td><td>姓名</td><td>性别</td><td>年龄</td>
        </tr>
        <tr><td>1001</td><td>张三</td><td>男</td><td>19</td>
        </tr>
        <tr><td>1002</td><td>李四</td><td>女</td><td>24</td>
        </tr>
        <tr><td>1003</td><td>王五</td><td>男</td><td>23</td>
        </tr>
    </tbody>
</table>

点击“查询学生按钮”,运行结果如下:

java 模拟ajax请求 javaweb ajax_ajax_02

三、DOM 和JavaScript

3.1 DOM的概念

DOM(Document Object Model)指的是文档对象模型,它是W3C的一个规范,可以用一种独立平台和语言的方式访问和修改文档的内容和结构。DOM是面向HTML 和XML 文档的API,为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。文档中的每个元素都是DOM的一部分。在HTML页面通常使用JavaScript 脚本语言来访问DOM。
一个web页面是一个文档。这个文档可以在浏览器窗口或作为HTML源码显示出来。但上述两个情况中都是同一份文档。文档对象模型(DOM)提供了对同一份文档的另一种表现,存储和操作的方式。 DOM是web页面的完全的面向对象表述,它能够使用如 JavaScript等脚本语言进行修改。

3.2 DOM 与 JavaScript

DOM 与JavaScript 很容易混淆。DOM是面向HTML 和XML 文档的API,为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。
人们一般使用JavaScript代码,通过 **DOM 来访问文档和其中的元素。**DOM 并不是一个编程语言,但如果没有DOM, JavaScript 语言也不会有任何网页,XML页面以及涉及到的元素的概念或模型。在文档中的每个元素— 包括整个文档,文档头部, 文档中的表格,表头,表格中的文本都是文档所属于的文档对象模型(DOM)的一部分,因此它们可以使用DOM和一个脚本语言如 JavaScript,来访问和处理。

开始的时候,JavaScript和DOM是交织在一起的,但它们最终演变成了两个独立的实体。JavaScript可以访问和操作存储在DOM中的内容,因此我们可以写成这个近似的等式:

API (web 或 XML 页面) = DOM + JS (脚本语言)

DOM 被设计成与特定编程语言相独立,使文档的结构化表述可以通过单一,一致的API获得,DOM 也可以使用除JavaScript以外的其他的语言来实现。

用于处理XML文档的DOM元素属性

属性名

说明

chilNodes

返回当前元素所有子元素的数组

firstChild

返回当前元素的第一个下级子元素

lastChild

返回当前元素的最后一个子元素

nextSibling

返回紧跟在当前元素后面的元素

previousSibling

返回紧邻当前元素之前的元素

nodeValue

返回节点值

parentNode

返回元素的父节点

遍历XML 文档的DOM 元素方法

方法名

说明

getElementById(id)

返回文档中由id指定的元素

getElementByTagName(name)

返回当前元素中指定标记名的子元素的数组

hasChildNodes()

返回一个布尔值,指示元素是否有子元素

getAttribute(name)

返回指定名称的元素的属性值

3.3 使用DOM动态编辑页面

属性/方法

描述

document.createElement(tagName)

文档对象上的createElement方法可以创建由tagName指定的元素。如果以串div作为方法参数,就会生成一个div元素

document.createTextNode(text)

文档对象的createTextNode方法会创建一个包含静态文本的节点

<element>.appendChild(childNode)

appendChild方法将指定的节点增加到当前元素的子节点列表(作为一个新的子节点)。例如,可以增加一个option元素,作为select元素的子节点

<element>.getAttribute(name)

获得元素中name属性的值

<element>.setAttribute(name, value)

设置元素中name属性的值

<element>.insertBefore(newNode, targetNode)

这个方法将节点newNode作为当前元素的子节点插到targetNode元素前面

<element>.removeAttribute(name)

这个方法从元素中删除属性name

<element>.removeChild(childNode)

这个方法从元素中删除子元素childNode

<element>.replaceChild(newNode, oldNode)

这个方法将节点oldNode替换为节点newNode

<element>.hasChildnodes()

这个方法返回一个布尔值,指示元素是否有子元素

实例:使用DOM和JavaScript创建动态内容

dynamicContent.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动态编辑网页</title>
    <script type="text/javascript">
        var xmlHttp;
        var requestType = "";
        function createXMLHttpRequest() {
            if (window.XMLHttpRequest) {
                xmlHttp = new XMLHttpRequest();
            }
            else {
                xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
        }
        function startRequest( requestedList) {
            requestType = requestedList;
            createXMLHttpRequest();
            xmlHttp.onreadystatechange = handleStateChange;
            xmlHttp.open("GET", "library.xml", "true");
            xmlHttp.send(null);
        }
        function handleStateChange() {
            if (xmlHttp.readyState == 4) {
                if (xmlHttp.status == 200) {
                    clearResults();
                    parseResults();
                }
            }
        }
        function clearResults(){
            var header = document.getElementById("header");
            if(header.hasChildNodes()){
                header.removeChild(header.childNodes[0]);
            }
            var tableBody = document.getElementById("resultsBody");
            while(tableBody.childNodes.length>0){
                tableBody.removeChild(tableBody.childNodes[0]);
            }
        }
        function parseResults(){
            var results = xmlHttp.responseXML;
            var items = null;
            var item = null;
            var books = null;
            var magazines = null;
            if(requestType == "books"){
                books = results.getElementsByTagName("books");
                items = books[0].getElementsByTagName("book");
                for(var i = 0;i<items.length;i++){
                    item = items[i];
                    name1 = item.getElementsByTagName("name")[0].firstChild.nodeValue;
                    author = item.getElementsByTagName("author")[0].firstChild.nodeValue;
                    year = item.getElementsByTagName("year")[0].firstChild.nodeValue;
                    price = item.getElementsByTagName("price")[0].firstChild.nodeValue;
                    addTableRow(name1,author,year,price);
                }
            }else if(requestType == "magazines"){
                magazines = results.getElementsByTagName("magazines");
                items = magazines[0].getElementsByTagName("magazine");
                for(var i = 0;i<items.length;i++){
                    item = items[i];
                    name1 = item.getElementsByTagName("name")[0].firstChild.nodeValue;
                    year = item.getElementsByTagName("year")[0].firstChild.nodeValue;
                    volume = item.getElementsByTagName("volume")[0].firstChild.nodeValue;
                    total = item.getElementsByTagName("total")[0].firstChild.nodeValue;
                    addTableRow(name1,year,volume,total);
                }
            }
            var header = document.createElement("p");
            var headerText = document.createTextNode("查询结果如下:");
            header.appendChild(headerText);
            document.getElementById("header").appendChild(header);
            document.getElementById("resultsTable").setAttribute("border","1");
        }

        function addTableRow(p1,p2,p3,p4) {
                var row = document.createElement("tr");
                var cell = createCellWithText(p1);
                row.appendChild(cell);
                cell = createCellWithText(p2);
                row.appendChild(cell);
                cell = createCellWithText(p3);
                row.appendChild(cell);
                cell = createCellWithText(p4);
                row.appendChild(cell);
                document.getElementById("resultsBody").appendChild(row);
        }
        function createCellWithText(text) {
             var cell = document.createElement("td");
             var textNode = document.createTextNode(text);
             cell.appendChild(textNode);
             return cell;
        }
    </script>
</head>
<body>
    <p>查看图书或杂志</p>
    <form action="#">
        <input type="button" value="查看图书" onclick="startRequest('books');" />
        <input type="button" value="查看杂志" onclick="startRequest('magazines');" />
    </form>
    <span id="header"></span>
    <table  id="resultsTable" border="0">
        <tbody id="resultsBody"></tbody>
    </table>
</body>
</html>

library.xml

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<library>
    <books>
        <book id="101">
            <name>Java</name>
            <author>张三</author>
            <year>2021.12</year>
            <price>88.50</price>
        </book>
        <book id="102">
            <name>Oracle</name>
            <author>李四</author>
            <year>2021.11</year>
            <price>33.80</price>
        </book>
        <book id="103">
            <name>MySql</name>
            <author>王五</author>
            <year>2021.12</year>
            <price>33.80</price>
        </book>
        <book id="104">
            <name>HTML</name>
            <author>小明</author>
            <year>2021.12</year>
            <price>33.80</price>
        </book>
    </books>
    <magazines>
        <magazine>
            <name>计算机网络</name>
            <year no="1">2021</year>
            <volume>21</volume>
            <total>147</total>
        </magazine>
        <magazine>
            <name>操作系统</name>
            <year no="1">2021</year>
            <volume>22</volume>
            <total>148</total>
        </magazine>
    </magazines>
</library>

四、AJAX的常用应用

4.1 AJAX适用场景

  1. 表单驱动的交互
  2. 深层次的树的导航
  3. 快速的用户与用户间的交流响应
  4. 类似投票、yes/no等无关痛痒的场景
  5. 对数据进行过滤和操纵相关数据的场景
  6. 普通的文本输入提示和自动完成的场景

4.2 AJAX不适用场景

  1. 部分简单的表单
  2. 搜索
  3. 基本的导航
  4. 替换大量的文本
  5. 对呈现的操纵