ajax(asynchronouse javascript and xml) 異步的javascript 和 xml(如今常把xml換成json):javascript
ajax是2005年提出的,在2006,2007年迅速的發展,目前不少網站都使用了ajax技術,在招聘軟件工程師時,ajax技術是必需要求掌握的。ajax技術包含了幾種技術:javascript、xml、css、xstl、dom、xhtml和XMLHttpRequest七種技術,因此ajax就像是粘合劑把七種技術整合到一塊兒,從而發揮各個技術的優點,威力驚人。[新瓶裝舊酒,組合拳]ajax是一個與服務端語言無關的技術. 便可以使用在(php/java ee/.net網站/ asp)ajax能夠給客戶端返回三種格式數據(文本格式 ,xml , json格式)php
爲何ajax會如此流行,必然有它的道理。ajax技術解決了不少其它技術解決不了的問題,好比:css
(1)頁面無刷新的動態數據交換html
(2)局部刷新頁面【驗證用戶名惟一】java
(3)界面的美觀 【加強用戶體驗】node
(4)對數據庫的操做web
(5)能夠返回簡單的文本格式,也能夠返回 xml文件格式, json數據格式ajax
ajax技術的意義:數據庫
互聯網的鏈接是不穩定,誰也不肯意看着本身的電腦從服務器一點一滴的下載數據,那麼,ajax是否是解決了這個問題呢,說實話,與其說ajax解決了這個問題,倒不如它只是掩蓋了這個問題,它只是在服務器和客戶端之間充當了一個緩衝器,讓用戶誤覺得服務沒有中斷。精確的說,ajax並不能提升從服務器端下載數據的速度,而只是使這個等待不那麼使人沮喪。可是正是這一點就足以產生巨大的影響和震動,它實際上也對桌面軟件產生了巨大的衝擊。編程
ajax在什麼地方用的多
1 動態加載數據,按需取得數據。【樹形菜單、聯動菜單…/省市聯動】
2 改善用戶體驗。【輸入內容前提示、帶進度條文件上傳…】
3 電子商務應用。 【購物車、郵件訂閱…】
4 訪問第三方服務。 【訪問搜索服務、rss閱讀器】
ajax 的運行原理分析:
PS:最重要的就是要弄透這四道線,其中4號線須要一個回調函數來實現。
Ajax的原理簡單來講經過XmlHttpRequest對象來向服務器發異步請求,從服務器得到數據,而後用javascript來操做DOM而更新頁面。這其中最關鍵的一步就是從服務器得到請求數據。要清楚這個過程和原理,咱們必須對 XMLHttpRequest有所瞭解。XMLHttpRequest是ajax的核心機制,它是在IE5中首先引入的,是一種支持異步請求的技術。簡單的說,也就是javascript能夠及時向服務器提出請求和處理響應,而不阻塞用戶。達到無刷新的效果。
咱們先來看看XMLHttpRequest這個對象的屬性。
它的屬性有:
onreadystatechange 每次狀態改變所觸發事件的事件處理程序。
responseText 從服務器進程返回數據的字符串形式。
responseXML 從服務器進程返回的DOM兼容的文檔數據對象(document)。
status 從服務器返回的數字代碼,好比常見的404(未找到)和200(已就緒)
status Text 伴隨狀態碼的字符串信息
readyState 對象狀態值
0 (未初始化) 對象已創建,可是還沒有初始化(還沒有調用open方法)
1 (初始化) 對象已創建,還沒有調用send方法
2 (發送數據) send方法已調用,可是當前的狀態及http頭未知
3 (數據傳送中) 已接收部分數據,由於響應及http頭不全,這時經過responseBody和responseText獲取部分數據會出現錯誤,
4 (完成) 數據接收完畢,此時能夠經過經過responseXml和responseText獲取完整的迴應數據
使用ajax與服務器通訊的的步驟
建立一個XMLHttpRequest對象(第一道線)
不一樣的瀏覽器建立 XMLHttpRequest 對象的方法是有差別的.咱們使用js 的try..catch..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
function getXmlHttp()
{
var xmlHttp;
try{
// Firefox, Opera 8.0+, Safari
xmlHttp=new XMLHttpRequest();}
catch (e){
// Internet Explorer
try{
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");}
catch (e){
try{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");}
catch (e){
alert("您的瀏覽器不支持AJAX!");
return false;}}
}}
|
建立url,data,經過 send(),發送請求。(第二道線)
服務器端接收 ajax的請求,作相應處理(操做數據庫),而後返回結果。(第三道線)
客戶端經過xmlHttpRequest的屬性 reponseText , responseXML 取的數據,而後就完成局部刷新當前頁面任務。(第四道線)
經典案例:
■ ajax經典案例—無刷新驗證用戶名
在用戶註冊時:
1 傳統的方法是把用戶填寫的全部信息都提交到服務器,若是用戶名重複,就會出異常。
2 若是使用ajax咱們能夠只提交用戶名,確認用戶名是否存在,再讓用戶點擊註冊。
配置文件(僅使用了servlet):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi
:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID"
version="3.1">
<servlet>
<servlet-name>ZMC</servlet-name>
<servlet-class>com.Register</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ZMC</servlet-name>
<url-pattern>/register</url-pattern>
</servlet-mapping>
</web-app>
|
服務端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package com;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Register extends HttpServlet {
private static final long serialVersionUID = 1L;
public Register() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
if(!request.getParameter("user").equals("zmc")){
response.getWriter().println("這個名字能夠註冊");//三號線
}
else{
response.getWriter().println("這個名字不能夠註冊");//三號線
}
}
}
|
客戶端請求頁面:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>無刷新驗證用戶名</title>
<script type="text/javascript">
//建立ajax引擎
//原理圖中的一號線
function getXmlHttpObject(){
var xmlHttpRequest;
//不一樣的瀏覽器獲取對象XmlHttpRequest 對象方法不同
if(window.ActiveXObject){
xmlHttpRequest=new ActiveXObject("Microsoft.XMLHTTP");
}else{
xmlHttpRequest=new XMLHttpRequest();
}
return xmlHttpRequest;
}
var myXmlHttpRequest=null;//設置全局變量
//驗證用戶名是否存在
function checkName(){
myXmlHttpRequest=getXmlHttpObject();
//判斷XMLHttpRequest對象是否建立成功
if(myXmlHttpRequest){
//經過myXmlHttpRequest對象發送請求到服務器的某個頁面
//第一個參數表示請求的方式, "get" / "post"
//第二個參數指定url,對哪一個頁面發出ajax請求(本質仍然是http請求)
//第三個參數表示 true表示使用異步機制,若是false表示不使用異步
var data="user="+$('username').value;
var url="/AjaxDemo/register";
//打開請求.
myXmlHttpRequest.open("post",url,true);
myXmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
myXmlHttpRequest.setRequestHeader("RequestType","ajax");
//指定回調函數.chuli是函數名
//注意在Ajax中函數是調用,函數()是引用函數地址
//狀態改變的事件觸發器,共四種狀態
myXmlHttpRequest.onreadystatechange=chuli;
//真的發送請求,若是是get請求則填入 null便可
//若是是post請求,則填入實際的數據
//這就是原理圖中的二號線
//若是是get方法,參數寫null
myXmlHttpRequest.send(data);
}
}
//回調函數
//一次請求回調函數會被調用四次,分爲四種狀態,咱們關心的是第四種狀態即:完成
//原理圖中的四號線
function chuli(){
//window.alert("處理函數被調回"+myXmlHttpRequest.readyState);
//我要取出從registerPro.php頁面返回的數據
if(myXmlHttpRequest.readyState==4){//最好把響應狀態碼爲200也加入判斷
//取出值,根據返回信息的格式定.text
//window.alert("服務器返回"+myXmlHttpRequest.responseText);
$('myRes').value=myXmlHttpRequest.responseText;
}
}
//這裏咱們寫一個函數,通常根據id取元素函數名都寫爲$
function $(id){
return document.getElementById(id);
}
</script>
</head>
<body>
<!--
onkeyup:鍵入一個字符便會觸發它,在這個例子中即是調用checkName()函數。
-->
<form action="???" method="post">
用戶名字
:<input type="text" onkeyup="checkName();" name="username1" id="username">
<input type="button" onclick="checkName();" value="驗證用戶名">
<input style="border-width: 0;color: red" type="text" id="myRes">
<br/>
用戶密碼
:<input type="password" name="password"><br>
電子郵件
:<input type="text" name="email"><br/>
<input type="submit" value="用戶註冊">
</form>
<form action="???" method="post">
用戶名字
:<input type="text" name="username2" >
<br/>
用戶密碼
:<input type="password" name="password"><br>
電子郵件
:<input type="text" name="email"><br/>
<input type="submit" value="用戶註冊">
</form>
</body>
</html>
|
響應結果圖:
PS:使用get方式發出請求,若是提交的用戶名不變化,瀏覽器將不會真的發請求,而是緩存取數據., url解決方法
1
|
var url="/ajax/registerProcess.php?mytime="+new Date()+"&username="+$("username").value;
|
//這裏兩句話很重要,第一講話告訴瀏覽器返回的數據是xml格式
header(「Content-Type: text/xml;charset=utf-8」);
//告訴瀏覽器不要緩存數據
header(「Cache-Control: no-cache」);
AJAX 能夠在php項目,java ee項目,.net項目使用。在服務器端的業務邏輯層使用何種服務器端語言均可以。
從服務器端接收數據的時候,那些數據必須以瀏覽器可以理解的格式來發送。服務器端的編程語言通常以以下 3 種格式返回數據:Text(又稱Html格式)、XML、JSON。
返回Html格式
HTML 由一些普通文本組成。若是服務器經過 XMLHttpRequest 發送 HTML, 文本將存儲在 responseText 屬性中。
沒必要從 responseText 屬性中讀取數據。它已是但願的格式,能夠直接將它插入到頁面中。
插入 HTML 代碼最簡單的方法是更新這個元素的 innerHTML 屬性。
innerHTML 並不是 DOM 標準。
■ 返回xml格式優勢:
XML 是一種通用的數據格式。沒必要把數據強加到已定義好的格式中,而是要爲數據自定義合適的標記。利用 DOM 能夠徹底掌控文檔。
缺點:若是文檔來自於服務器,就必須得保證文檔含有正確的首部信息。若文檔類型不正確,那麼 responseXML 的值將是空的。當瀏覽器接收到長的 XML 文件後, DOM 解析可能會很複雜
PS:不論是返回的何種類型,影響的只是三四號線
上面的那個例子即是返回了text格式,如今仍是拿上面那個例子返回xml 格式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
function chuli(){
if(myXmlHttpRequest.readyState==4){
//看看若是取出 xml格式數據,返回的是document對象,xml //dom
//獲取mes節點
var mes=myXmlHttpRequest.responseXML.getElementsByTagName("mes");
//取出mes節點值
//mes[0]->表示取出第一個mes節點
//mes[0].childNodes[0]->表示第一個mes節點的第一個子節點
var mes_val=mes[0].childNodes[0].nodeValue;
$('myres').value=mes_val;
}
}
//這裏兩句話很重要,第一講話告訴瀏覽器返回的數據是xml格式
header("Content-Type: text/xml;charset=utf-8");
//告訴瀏覽器不要緩存數據
header("Cache-Control: no-cache");
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
if(!request.getParameter("user").equals("zmc")){
response.getWriter().println("<res><mes>用戶名不能夠用,對不起</mes></res>");//三號線
}
|
返回JSON格式:(推薦)
JSON 只是一種文本字符串。它被存儲在 responseText 屬性中。爲了讀取存儲在 responseText 屬性中的 JSON 數據,須要根據 JavaScript 的 eval 語句。函數 eval 會把一個字符串看成它的參數。而後這個字符串會被看成 JavaScript 代碼來執行。由於 JSON 的字符串就是由 JavaScript 代碼構成的,因此它自己是可執行的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
String str="{'ceshi':'這個名字能夠註冊'}";
String str2="{'ceshi':'這個名字不能夠註冊'}";
if(!request.getParameter("user").equals("zmc")){
response.getWriter().println(str);//三號線
}
else{
response.getWriter().println(str2);//三號線
}
}
}
function chuli(){
if(myXmlHttpRequest.readyState==4){
//取出值,根據返回信息的格式json字符串 //window.alert("服務器返回"+myXmlHttpRequest.responseText);
var str = myXmlHttpRequest.responseText;
var json = eval("("+str+")");
$('myRes').value=json.ceshi;
}
|
小結:
當一個ajax請求到服務器,服務器能夠根據需求返回 三種格式的數據,那麼咱們應當選擇哪個?
■ ajax經典案例—省市聯動
ajax一個最重要的用途就是,動態的從服務器取須要的數據,並在頁面無刷新的顯示,咱們來看一個經典的用法:省市聯動菜單:
1 傳統的b/s中,顯示省市聯動菜單是一次性把數據所有取出,並在客戶端顯示,這樣作數據傳輸量大,不靈活。
2 使用ajax技術,能夠根據用戶需求從服務器取數據,當用戶點擊某個按鈕時,才從服務器取數據並顯示,靈活。讓學生從數據庫取出數據,縣城級別聯動作出.
ajax的省市聯動案例(如何動態的從服務器取得數據),這裏只貼了一部分代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
function getCities(){
myXmlHttpRequest=getXmlHttpObject();
if(myXmlHttpRequest){
var url="/ajax/showCitiesPro.php";//post
var data="province="+$('sheng').value;
myXmlHttpRequest.open("post",url,true);//異步方式
myXmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
//指定回調函數
myXmlHttpRequest.onreadystatechange=chuli;
//發送
myXmlHttpRequest.send(data);
}
}
function chuli(){
if(myXmlHttpRequest.readyState==4){
if(myXmlHttpRequest.status==200){
//取出服務器回送的數據
var cities=myXmlHttpRequest.responseXML.getElementsByTagName("city");
$('city').length=0;
var myOption=document.createElement("option");
myOption.innerText="--城市--";
//添加到
$('city').appendChild(myOption);
//遍歷並取出城市
for(var i=0;i<cities.length;i++){
var city_name=cities[i].childNodes[0].nodeValue;
//建立新的元素option
var myOption=document.createElement("option");
myOption.value=city_name;
myOption.innerText=city_name;
//添加到
$('city').appendChild(myOption);
}
}
}
}
//這裏咱們寫一個函數
function $(id){
return document.getElementById(id);
}
</script>
</head>
<body>
<select id="sheng" onchange="getCities();">
<option value="">---省---</option>
<option value="zhejiang">浙江</option>
<option value="jiangsu" >江蘇</option>
<option value="sichuan" >四川</option>
</select>
<select id="city">
<option value="">--城市--</option>
</select>
<select id="county">
<option value="">--縣城--</option>
</select>
</body>
</html>
**showCitiesProcess.php**
<?php
//服務器端
//這裏兩句話很重要,第一講話告訴瀏覽器返回的數據是xml格式
header("Content-Type: text/xml;charset=utf-8");
//告訴瀏覽器不要緩存數據
header("Cache-Control: no-cache");
//接收用戶的選擇的省的名字
$province=$_POST['province'];
file_put_contents("d:/mylog.log",$province."\r\n",FILE_APPEND);
//如何在調試過程當中,看到接收到的數據 。
//到數據庫去查詢省有那些城市(如今先不到數據庫)
$info="";
if($province=="zhejiang"){
$info="<province><city>杭州</city><city>溫州</city><city>寧波</city></province>";
}else if($province=="jiangsu"){
$info="<province><city>南京</city><city>徐州</city><city>蘇州</city></province>";
}
echo $info;
?>
|
PS:服務器不可能主動給客戶端發消息,拿手機收到短信舉例,實際上是手機上有一個發射器,它會在規定時間內如2秒定時去服務器上的數據庫中查找是否有本身未接收的短信,若是有就接收到。