jizz在线观看视频,久久亚洲欧美,天堂中文在线资http://www.aygfsteel.com/zhangrenquan/category/6018.htmlzh-cnThu, 15 Nov 2012 05:44:18 GMTThu, 15 Nov 2012 05:44:18 GMT60DWR讓AJAX如此簡單http://www.aygfsteel.com/zhangrenquan/articles/162106.htmlkelvenkelvenWed, 21 Nov 2007 07:48:00 GMThttp://www.aygfsteel.com/zhangrenquan/articles/162106.htmlhttp://www.aygfsteel.com/zhangrenquan/comments/162106.htmlhttp://www.aygfsteel.com/zhangrenquan/articles/162106.html#Feedback0http://www.aygfsteel.com/zhangrenquan/comments/commentRss/162106.htmlhttp://www.aygfsteel.com/zhangrenquan/services/trackbacks/162106.htmlhttp://www.java-ren.com/article/2007/9/27/2007927111512398.html

kelven 2007-11-21 15:48 發表評論
]]>
XMLHttpRequest對象池http://www.aygfsteel.com/zhangrenquan/articles/81915.htmlkelvenkelvenSat, 18 Nov 2006 05:38:00 GMThttp://www.aygfsteel.com/zhangrenquan/articles/81915.htmlhttp://www.aygfsteel.com/zhangrenquan/comments/81915.htmlhttp://www.aygfsteel.com/zhangrenquan/articles/81915.html#Feedback1http://www.aygfsteel.com/zhangrenquan/comments/commentRss/81915.htmlhttp://www.aygfsteel.com/zhangrenquan/services/trackbacks/81915.html在ajax應用中,通常一個頁面要同時發送多個請求,如果只有一個XMLHttpRequest對象,前面的請求還未完成,后面的就會把前面的覆蓋掉,如果每次都創建一個新的XMLHttpRequest對象,也會造成浪費。解決的辦法就是創建一個XMLHttpRequset的對象池,如果池里有空閑的對象,則使用此對象,否則將創建一個新的對象。

下面是我最近寫的一個簡單的類:

/**
?*?XMLHttpRequest?Object?Pool
?*
?*?@author????legend?<legendsky@hotmail.com>
?*?@link??????http://www.ugia.cn/?p=85
?*?@Copyright?www.ugia.cn
?*/?

var? XMLHttp? =?{
????
_objPool :?[],

????
_getInstance :?function?()
????{
????????for?(var?
i? =? 0 ;? i? <? this . _objPool . length ;? i? ++)
????????{
????????????if?(
this . _objPool [ i ]. readyState? ==? 0? ||? this . _objPool [ i ]. readyState? ==? 4 )
????????????{
????????????????return?
this . _objPool [ i ];
????????????}
????????}

????????
//?IE5中不支持push方法
????????
this . _objPool [ this . _objPool . length ]?=? this . _createObj ();

????????return?
this . _objPool [ this . _objPool . length? -? 1 ];
????},

????
_createObj :?function?()
????{
????????if?(
window . XMLHttpRequest )
????????{
????????????var?
objXMLHttp? =?new? XMLHttpRequest ();

????????}
????????else
????????{
????????????var?
MSXML? =?[ 'MSXML2.XMLHTTP.5.0' ,? 'MSXML2.XMLHTTP.4.0' ,? 'MSXML2.XMLHTTP.3.0' ,? 'MSXML2.XMLHTTP' ,? 'Microsoft.XMLHTTP' ];
????????????for(var?
n? =? 0 ;? n? <? MSXML . length ;? n? ++)
????????????{
????????????????
try
????????????????
{
????????????????????var?
objXMLHttp? =?new? ActiveXObject ( MSXML [ n ]);
????????????????????break;
????????????????}
????????????????
catch ( e )
????????????????{
????????????????}
????????????}
?????????}??????????

????????
//?mozilla某些版本沒有readyState屬性
????????
if?( objXMLHttp . readyState? ==? null )
????????{
????????????
objXMLHttp . readyState? =? 0 ;

????????????
objXMLHttp . addEventListener ( "load" ,?function?()
????????????????{
????????????????????
objXMLHttp . readyState? =? 4 ;

????????????????????if?(
typeof?objXMLHttp . onreadystatechange? ==? "function" )
????????????????????{
????????????????????????
objXMLHttp . onreadystatechange ();
????????????????????}
????????????????},??
false );
????????}

????????return?
objXMLHttp ;
????},

????
//?發送請求(方法[post,get],?地址,?數據,?回調函數)
????
sendReq :?function?( method ,? url ,? data ,? callback )
????{
????????var?
objXMLHttp? =? this . _getInstance ();

????????
with ( objXMLHttp )
????????{
????????????
try
????????????
{
????????????????
//?加隨機數防止緩存
????????????????
if?( url . indexOf ( "?" )?>? 0 )
????????????????{
????????????????????
url? +=? "&randnum="? +? Math . random ();
????????????????}
????????????????else
????????????????{
????????????????????
url? +=? "?randnum="? +? Math . random ();
????????????????}

????????????????
open ( method ,? url ,? true );

????????????????
//?設定請求編碼方式
????????????????
setRequestHeader ( 'Content-Type' ,? 'application/x-www-form-urlencoded;?charset=UTF-8' );
????????????????
send ( data );
????????????????
onreadystatechange? =?function?()
????????????????{
????????????????????if?(
objXMLHttp . readyState? ==? 4? &&?( objXMLHttp . status? ==? 200? ||? objXMLHttp . status? ==? 304 ))
????????????????????{
????????????????????????
callback ( objXMLHttp );
????????????????????}
????????????????}
????????????}
????????????
catch ( e )
????????????{
????????????????
alert ( e );
????????????}
????????}
????}
};?

示例:

< script?type = "text/javascript"? src = "xmlhttp.js" > </script>
<script?type="text/javascript">
function?test(obj)
{
????alert(obj.statusText);
}

XMLHttp.sendReq('GET',?'http://www.ugia.cn/wp-data/test.htm',?'',?test);
XMLHttp.sendReq('GET',?'http://www.ugia.cn/wp-data/test.htm',?'',?test);
XMLHttp.sendReq('GET',?'http://www.ugia.cn/wp-data/test.htm',?'',?test);
XMLHttp.sendReq('GET',?'http://www.ugia.cn/wp-data/test.htm',?'',?test);

alert('Pool?length:'?+?XMLHttp._objPool.length);
</script>?

源代碼里有中文的注釋,是ansi的,如果你的網站或ie下選擇編碼為UTF-8,可能會導致錯誤,你把你ie的編碼改成gb2312看看,或者去掉文件里的中文注釋



kelven 2006-11-18 13:38 發表評論
]]>
xmlhttp與防盜鏈http://www.aygfsteel.com/zhangrenquan/articles/57846.htmlkelvenkelvenWed, 12 Jul 2006 10:14:00 GMThttp://www.aygfsteel.com/zhangrenquan/articles/57846.htmlhttp://www.aygfsteel.com/zhangrenquan/comments/57846.htmlhttp://www.aygfsteel.com/zhangrenquan/articles/57846.html#Feedback0http://www.aygfsteel.com/zhangrenquan/comments/commentRss/57846.htmlhttp://www.aygfsteel.com/zhangrenquan/services/trackbacks/57846.html
在這個文件中,我們可以用很多方法來判斷用戶身份,包括來源的url,cookie數據,甚至是ip標志等。

<%@ codepage=65001%>

<%

Response.Buffer=False

re_url = Lcase(Request.ServerVariables("HTTP_REFERER"))

'獲得來源頁面的url

mydomain = Lcase(Request.ServerVariables("SERVER_NAME"))

'獲得本頁面域名 也可以直接指定

if mid(re_url,8,len(mydoain)) <> mydomian then

response.write "URL wrong"

'or redirect

response.end()

end if

%>

//niceidea 簽名留念

這個是用的最多的防止盜鏈的方法,檢查鏈入的頁面是否是外地人,如果是外部鏈入,拒絕下載。

這里更保險的辦法是利用cookie驗證,就象通常的點擊廣告后才可以看到地址的方法一樣。

最好的辦法是裝一個防盜鏈軟件,asp腳本比較是基于iis的。<%

dim file_url,objXMLHTTP

file_url="http://localhost/11.rar"

'我們可以從數據庫中讀取軟件

Set objXMLHTTP = Server.CreateObject("Msxml2.ServerXMLHTTP")

objXmlHttp.open "GET",file_url,false

objXmlHttp.send()If objXMLHTTP.Status<>"200" Then

response.write("file missing。")

else

Response.ContentType = "application/octet-stream"

Response.AddHeader "content-disposition", "attachment; filename=" & "11.rar"

Response.BinaryWrite objXMLHTTP.responseBody

End IfSet obiXMLHTTP=nothing

response.end()

%>這個辦法有明顯的弊端,它需要在服務器內部交換一次數據,從而加重了服務器的負擔,類似于開了一個暫時的代理;這里最好設置response的緩沖屬性為false,iis6.0的asp緩存大小為4m,大的文件或者多個文件的緩沖很容易讓服務器當機。

不過它的好處是防止盜鏈,因為這里沒有發送任何關于真實地址的信息到最終的客戶端。

更有效的使用途徑是解決某些站點的圖片防盜鏈功能.

例如網易相冊,就有防止跨域盜鏈的功能。

下面的文件:

<html>

<body>

<img src="http://img301.photo.163.com/luomin_dvd/35412650/__scale__1_954873822.jpg"/>

<img src="getimg.asp?imgsrc=http://img301.photo.163.com/luomin_dvd/35412650/__scale__1_954873822.jpg"/>

</body>

</html>

然后另寫一個getimg.asp

<%

response.buffer=True

dim file_url

file_url=request.querystring("imgsrc")

Set objXMLHTTP = Server.CreateObject("Msxml2.ServerXMLHTTP")

objXmlHttp.open "GET",file_url,false

objXmlHttp.send()

Response.ContentType = "image/jepg"

Response.BinaryWrite objXMLHTTP.responseBody

set objXMLHTTP=nothing

%>

你會發現,第一張圖片是個×,第二張則正常。

在使用getimg.asp的時候,注意你的iis是否安裝了防盜鏈軟件,最好不要讓別人盜鏈了。

kelven 2006-07-12 18:14 發表評論
]]>
XMLHttp常用屬性,方法,成員http://www.aygfsteel.com/zhangrenquan/articles/57845.htmlkelvenkelvenWed, 12 Jul 2006 10:13:00 GMThttp://www.aygfsteel.com/zhangrenquan/articles/57845.htmlhttp://www.aygfsteel.com/zhangrenquan/comments/57845.htmlhttp://www.aygfsteel.com/zhangrenquan/articles/57845.html#Feedback2http://www.aygfsteel.com/zhangrenquan/comments/commentRss/57845.htmlhttp://www.aygfsteel.com/zhangrenquan/services/trackbacks/57845.html XMLHttpRequest對象

onreadystatechange屬性

readyState屬性

responsebody屬性

responsestream屬性

responsetext屬性

responsexml成員

status成員

statusText成員

abort方法

getallresponseheaders方法

getResponseHeader方法

open方法

send方法

setrequestheader方法


xmlhttp:onreadystatechange屬性
onreadystatechange

指定當readyState屬性改變時的事件處理句柄
語法

oXMLHttpRequest.onreadystatechange = funcMyHandler;

Example

如下的例子演示當XMLHTTPRequest對象的readyState屬性改變時調用HandleStateChange函數,當數據接收完畢后(readystate == 4)此頁面上的一個按鈕將被激活

var xmlhttp=null;
function PostOrder(xmldoc)
{
var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.5.0");
xmlhttp.Open("POST", "http://myserver/orders/processorder.asp", false);
xmlhttp.onreadystatechange= HandleStateChange;
xmlhttp.Send(xmldoc);
myButton.disabled = true;
}
function HandleStateChange()
{
if (xmlhttp.readyState == 4)
{
myButton.disabled = false;
alert("Result = " + xmlhttp.responseXML.xml);
}
}


?

XMLHttpRequest對象
XMLHttpRequest

提供客戶端同http服務器通訊的協議
Example

下面的代碼是在JScript中創建一個XMLHTTP對象并從服務器請求一個XML文檔。服務器返回XML文檔并顯示。

var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
xmlHttpReq.open("GET", "http://localhost/books.xml", false);
xmlHttpReq.send();
alert(xmlHttpReq.responseText);

在非IE的瀏覽器中,需要用new XMLHttpRequest()來創建對象,如下:

var xmlHttpReq = new XMLHttpRequest();
xmlHttpReq.open("GET", "http://localhost/books.xml", false);
xmlHttpReq.send();
alert(xmlHttpReq.responseText);

vbscript:

Dim HttpReq As New MSXML2.XMLHTTP30
HttpReq.open "GET", "http://localhost/books.xml", False
HttpReq.send
MsgBox HttpReq.responseText

備注

客戶端可以通過XmlHttp對象(MSXML2.XMLHTTP.3.0)向http服務器發送請求并使用微軟XML文檔對象模型Microsoft? XML Document Object Model (DOM)處理回應。


xmlhttp:readyState屬性
readyState

返回XMLHTTP請求的當前狀態
語法

lValue = oXMLHttpRequest.readyState;

Example

var XmlHttp;
XmlHttp = new ActiveXObject("Msxml2.XMLHTTP.3.0");

function send() {
XmlHttp.onreadystatechange = doHttpReadyStateChange;
XmlHttp.open("GET", "http://localhost/sample.xml", true);
XmlHttp.send();
}

function doHttpReadyStateChange() {
if (XmlHttp.readyState == 4) {
alert("Done");
}
}

備注

變量,此屬性只讀,狀態用長度為4的整型表示.定義如下:
0 (未初始化) 對象已建立,但是尚未初始化(尚未調用open方法)
1 (初始化) 對象已建立,尚未調用send方法
2 (發送數據) send方法已調用,但是當前的狀態及http頭未知
3 (數據傳送中) 已接收部分數據,因為響應及http頭不全,這時通過responseBody和responseText獲取部分數據會出現錯誤,
4 (完成) 數據接收完畢,此時可以通過通過responseBody和responseText獲取完整的回應數據


?

xmlhttp:responsebody屬性
responseBody

返回某一格式的服務器響應數據
語法

strValue = oXMLHttpRequest.responseBody;

Example

var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.3.0");
xmlhttp.open("GET", "http://localhost/books.xml", false);
xmlhttp.send();
alert(xmlhttp.responseBody);

備注

變量,此屬性只讀,以unsigned array格式表示直接從服務器返回的未經解碼的二進制數據。
參考

responseStream 屬性
responseText 屬性


?

xmlhttp:responsestream屬性
responseStream

以Ado Stream對象的形式返回響應信息
語法

strValue = oXMLHttpRequest.responseStream;

備注

變量,此屬性只讀,以Ado Stream對象的形式返回響應信息。


?

xmlhttp:responsetext屬性
responseText

將響應信息作為字符串返回
語法

strValue = oXMLHttpRequest.responseText;

Example

var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.3.0");
xmlhttp.open("GET", "http://localhost/books.xml", false);
xmlhttp.send();
alert(xmlhttp.responseText);

備注

變量,此屬性只讀,將響應信息作為字符串返回。
XMLHTTP嘗試將響應信息解碼為Unicode字符串,XMLHTTP默認將響應數據的編碼定為UTF-8,如果服務器返回的數據帶BOM(byte -order mark),XMLHTTP可以解碼任何UCS-2 (big or little endian)或者UCS-4 數據。注意,如果服務器返回的是xml文檔,此屬性并不處理xml文檔中的編碼聲明。你需要使用responseXML來處理。


?

xmlhttprequest:responsexml成員
responseXML

將響應信息格式化為Xml Document對象并返回
語法

var objDispatch = oXMLHttpRequest.responseXML;

Example

var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.3.0");
xmlhttp.open("GET", "http://localhost/books.xml", false);
xmlhttp.send();
alert(xmlhttp.responseXML.xml);

備注

變量,此屬性只讀,將響應信息格式化為Xml Document對象并返回。如果響應數據不是有效的XML文檔,此屬性本身不返回XMLDOMParseError,可以通過處理過的DOMDocument對象獲取錯誤信息。


?

xmlhttprequest對象:status成員
status

返回當前請求的http狀態碼
語法

lValue = oXMLHttpRequest.status;

Example

var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.3.0");
xmlhttp.open("GET", "http://localhost/books.xml", false);
xmlhttp.send();
alert(xmlhttp.status);

返回值
長整形標準http狀態碼,定義如下:
Number Description

100

Continue

101

Switching protocols

200

OK

201

Created

202

Accepted

203

Non-Authoritative Information

204

No Content

205

Reset Content

206

Partial Content

300

Multiple Choices

301

Moved Permanently

302

Found

303

See Other

304

Not Modified

305

Use Proxy

307

Temporary Redirect

400

Bad Request

401

Unauthorized

402

Payment Required

403

Forbidden

404

Not Found

405

Method Not Allowed

406

Not Acceptable

407

Proxy Authentication Required

408

Request Timeout

409

Conflict

410

Gone

411

Length Required

412

Precondition Failed

413

Request Entity Too Large

414

Request-URI Too Long

415

Unsupported Media Type

416

Requested Range Not Suitable

417

Expectation Failed

500

Internal Server Error

501

Not Implemented

502

Bad Gateway

503

Service Unavailable

504

Gateway Timeout

505

HTTP Version Not Supported
備注

長整形,此屬性只讀,返回當前請求的http狀態碼,此屬性僅當數據發送并接收完畢后才可獲取。


?

xmlhttprequest:statusText成員
statusText

返回當前請求的響應行狀態
語法

strValue = oXMLHttpRequest.statusText;

Example

var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.3.0");
xmlhttp.open("GET", "http://localhost/books.xml", false);
xmlhttp.send();
alert(xmlhttp.statusText);

備注

字符串,此屬性只讀,以BSTR返回當前請求的響應行狀態,此屬性僅當數據發送并接收完畢后才可獲取。


?

xmlhttp:abort方法
abort

取消當前請求
語法

oXMLHttpRequest.abort();

備注

調用此方法后,當前請求返回UNINITIALIZED 狀態。


?

xmlhttp:getallresponseheaders方法
getallresponseheaders

獲取響應的所有http頭
語法

strValue = oXMLHttpRequest.getAllResponseHeaders();

Example

var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.3.0");
xmlhttp.open("GET", "http://localhost/sample.xml", false);
xmlhttp.send();
alert(xmlhttp.getAllResponseHeaders());

輸出由web服務器返回的http頭信息,example:

Server:Microsoft-IIS/5.1
X-Powered-By:ASP.NET
Date:Sat, 07 Jun 2003 23:23:06 GMT
Content-Type:text/xml
Accept-Ranges:bytes
Last Modified:Sat, 06 Jun 2003 17:19:04 GMT
ETag:"a0e2eeba4f2cc31:97f"
Content-Length:9

備注

每個http頭名稱和值用冒號分割,并以\r\n結束。當send方法完成后才可調用該方法。


?

xmlhttp:getResponseHeader方法
getResponseHeader

從響應信息中獲取指定的http頭
語法

strValue = oXMLHttpRequest.getResponseHeader(bstrHeader);

Example

var xmlhttp = new ActiveXObject("MSXML2.XMLHTTP.3.0");
xmlhttp.open("GET", "http://localhost/sample.xml", false);
xmlhttp.send();
alert(xmlhttp.getResponseHeader("Server"));

輸出http頭中的server列:當前web服務器的版本及名稱。
備注

當send方法成功后才可調用該方法。如果服務器返回的文檔類型為"text/xml", 則這句話xmlhttp.getResponseHeader("Content-Type");將返回字符串"text/xml"??梢允褂?getAllResponseHeaders方法獲取完整的http頭信息。


?

xmlhttp:open方法
open

創建一個新的http請求,并指定此請求的方法、URL以及驗證信息
語法

oXMLHttpRequest.open(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword);

參數

bstrMethod
http方法,例如:POST、GET、PUT及PROPFIND。大小寫不敏感。

bstrUrl
請求的URL地址,可以為絕對地址也可以為相對地址。

varAsync[可選]
布爾型,指定此請求是否為異步方式,默認為true。如果為真,當狀態改變時會調用onreadystatechange屬性指定的回調函數。

bstrUser[可選]
如果服務器需要驗證,此處指定用戶名,如果未指定,當服務器需要驗證時,會彈出驗證窗口。

bstrPassword[可選]
驗證信息中的密碼部分,如果用戶名為空,則此值將被忽略。
Example
下面的例子演示從服務器請求book.xml,并顯示其中的book字段。

var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.3.0");
xmlhttp.open("GET","http://localhost/books.xml", false);
xmlhttp.send();
var book = xmlhttp.responseXML.selectSingleNode("http://book[@id=''bk101'']");
alert(book.xml);

備注

調用此方法后,可以調用send方法向服務器發送數據。


?

xmlhttp:send方法
send

發送請求到http服務器并接收回應
語法

oXMLHttpRequest.send(varBody);

參數

varBody
欲通過此請求發送的數據。
Example

xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.3.0");
xmlhttp.open("GET", "http://localhost/sample.xml", false);
xmlhttp.send();
alert(xmlhttp.responseXML.xml);

備注

此方法的同步或異步方式取決于open方法中的bAsync參數,如果bAsync == False,此方法將會等待請求完成或者超時時才會返回,如果bAsync == True,此方法將立即返回。

This method takes one optional parameter, which is the requestBody to use. The acceptable VARIANT input types are BSTR, SAFEARRAY of UI1 (unsigned bytes), IDispatch to an XML Document Object Model (DOM) object, and IStream *. You can use only chunked encoding (for sending) when sending IStream * input types. The component automatically sets the Content-Length header for all but IStream * input types.

如果發送的數據為BSTR,則回應被編碼為utf-8, 必須在適當位置設置一個包含charset的文檔類型頭。

If the input type is a SAFEARRAY of UI1, the response is sent as is without additional encoding. The caller must set a Content-Type header with the appropriate content type.

如果發送的數據為XML DOM object,則回應將被編碼為在xml文檔中聲明的編碼,如果在xml文檔中沒有聲明編碼,則使用默認的UTF-8。

If the input type is an IStream *, the response is sent as is without additional encoding. The caller must set a Content-Type header with the appropriate content type.


?

xmlhttp:setrequestheader方法
setRequestHeader

單獨指定請求的某個http頭
語法

oXMLHttpRequest.setRequestHeader(bstrHeader, bstrValue);

參數

bstrHeader
字符串,頭名稱。
bstrValue
字符串,值。
備注

如果已經存在已此名稱命名的http頭,則覆蓋之。此方法必須在open方法后調用。

?

xmlhttp的請求同步和異步、方法的get和post
http://www.niceidea.org/post/xmlhttp_true_false_post_get.html

看看open方法的另外幾個參數。

.open http-method, url, async, userID, password (后面是帳號和密碼,在禁止匿名訪問的http頁面中,需要用戶名和口令)

首先看看異步處理方式。

其中async是一個布爾值。如果是異步通信方式(true),客戶機就不等待服務器的響應;如果是同步方式(false),客戶機就要等到服務器返回消息后才去執行其他操作。我們需要根據實際需要來指定同步方式,在某些頁面中,可能會發出多個請求,甚至是有組織有計劃有隊形大規模的高強度的request,而后一個是會覆蓋前一個的,這個時候當然要指定同步方式:Flase。

//niceidea 簽名留念

首先看看method,方法。

一個標準的http請求頭:

7/8/99 10:27:16 Sent GET /Store/Download.asp HTTP/1.1

Accept: application/msword, application/vnd.ms-execl, application/vnd.ms-

powerpoint, image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-

comet, */*

Accept-Language: en-us

Encoding: gzip, deflate

Referer: http://ww.wrox.com/main_menu.asp

Cookie: VisitCount=2&LASTDATE=6%2F4%2F99+10%3A10%3A13+AM

User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 98)

Host: 212.250.238.67

Connection: Keep-Alive

很容易看懂,其中的method包括post/get/put等。對應的主要是對于form即表單元素的處理方法。

當mothod值為get時,表單將附加在action頁面的url中;如果頁面是asp的,將會request.querystring中獲得;

如果是post,將會在request.form中獲得,

對應與put方法的表單寫法是:form method="POST" enctype='multipart/form-data'

主要用于上傳文件。

使用那種方法取決于服務端。



kelven 2006-07-12 18:13 發表評論
]]>
AJAX開發簡略http://www.aygfsteel.com/zhangrenquan/articles/55178.htmlkelvenkelvenMon, 26 Jun 2006 08:56:00 GMThttp://www.aygfsteel.com/zhangrenquan/articles/55178.htmlhttp://www.aygfsteel.com/zhangrenquan/comments/55178.htmlhttp://www.aygfsteel.com/zhangrenquan/articles/55178.html#Feedback0http://www.aygfsteel.com/zhangrenquan/comments/commentRss/55178.htmlhttp://www.aygfsteel.com/zhangrenquan/services/trackbacks/55178.html閱讀全文

kelven 2006-06-26 16:56 發表評論
]]>
AJAX輕松上路http://www.aygfsteel.com/zhangrenquan/articles/47574.htmlkelvenkelvenTue, 23 May 2006 01:23:00 GMThttp://www.aygfsteel.com/zhangrenquan/articles/47574.htmlhttp://www.aygfsteel.com/zhangrenquan/comments/47574.htmlhttp://www.aygfsteel.com/zhangrenquan/articles/47574.html#Feedback0http://www.aygfsteel.com/zhangrenquan/comments/commentRss/47574.htmlhttp://www.aygfsteel.com/zhangrenquan/services/trackbacks/47574.html 什么是 AJAX?

  AJAX (異步 JavaScript 和 XML) 是個新產生的術語,專為描述JavaScript的兩項強大性能.這兩項性能在多年來一直被網絡開發者所忽略,直到最近Gmail, Google suggest和google Maps的橫空出世才使人們開始意識到其重要性.

  這兩項被忽視的性能是:

??無需重新裝載整個頁面便能向服務器發送請求.
??對XML文檔的解析和處理.

  步驟 1 – "請!" --- 如何發送一個HTTP請求

  為了用JavaScript向服務器發送一個HTTP請求, 需要一個具備這種功能的類實例. 這樣的類首先由Internet Explorer以ActiveX對象引入, 被稱為XMLHTTP. 后來Mozilla, Safari 和其他瀏覽器紛紛仿效, 提供了XMLHttpRequest類,它支持微軟的ActiveX對象所提供的方法和屬性.

  因此, 為了創建一個跨瀏覽器的這樣的類實例(對象), 可以應用如下代碼:

if (window.XMLHttpRequest) { // Mozilla, Safari, ...
??? http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
??? http_request = new ActiveXObject("Microsoft.XMLHTTP");
}

  (上例對代碼做了一定簡化,這是為了解釋如何創建XMLHTTP類實例. 實際的代碼實例可參閱本篇步驟3.)

  如果服務器的響應沒有XML mime-type header,某些Mozilla瀏覽器可能無法正常工作. 為了解決這個問題, 如果服務器響應的header不是text/xml,可以調用其它方法修改該header.

http_request = new XMLHttpRequest();
http_request.overrideMimeType('text/xml');

  接下來要決定當收到服務器的響應后,需要做什么.這需要告訴HTTP請求對象用哪一個JavaScript函數處理這個響應.可以將對象的onreadystatechange屬性設置為要使用的JavaScript的函數名,如下所示:

http_request.onreadystatechange = nameOfTheFunction;

  注意:在函數名后沒有括號,也無需傳遞參數.另外還有一種方法,可以在扉頁(fly)中定義函數及其對響應要采取的行為,如下所示:

http_request.onreadystatechange = function(){
??? // do the thing
};

  在定義了如何處理響應后,就要發送請求了.可以調用HTTP請求類的open()和send()方法, 如下所示:

http_request.open('GET', 'http://www.example.org/some.file', true);
http_request.send(null);

??open()的第一個參數是HTTP請求方式 – GET, POST, HEAD 或任何服務器所支持的您想調用的方式. 按照HTTP規范,該參數要大寫;否則,某些瀏覽器(如Firefox)可能無法處理請求.有關HTTP請求方法的詳細信息可參考http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html W3C specs
??第二個參數是請求頁面的URL.由于自身安全特性的限制,該頁面不能為第三方域名的頁面.同時一定要保證在所有的頁面中都使用準確的域名,否則調用open()會得到"permission denied"的錯誤提示.一個常見的錯誤是訪問站點時使用domain.tld,而當請求頁面時,卻使用www.domain.tld.
??第三個參數設置請求是否為異步模式.如果是TRUE, JavaScript函數將繼續執行,而不等待服務器響應.這就是"AJAX"中的"A".

  如果第一個參數是"POST",send()方法的參數可以是任何想送給服務器的數據. 這時數據要以字符串的形式送給服務器,如下所示:

name=value&anothername=othervalue&so=on

  步驟 2 – "收到!" --- 處理服務器的響應

  當發送請求時,要提供指定處理響應的JavaScript函數名.

http_request.onreadystatechange = nameOfTheFunction;

  我們來看看這個函數的功能是什么.首先函數會檢查請求的狀態.如果狀態值是4,就意味著一個完整的服務器響應已經收到了,您將可以處理該響應.

if (http_request.readyState == 4) {
??? // everything is good, the response is received
} else {
??? // still not ready
}

  readyState的取值如下:

??0 (未初始化)
??1 (正在裝載)
??2 (裝載完畢)
??3 (交互中)
??4 (完成)
(Source)

  接著,函數會檢查HTTP服務器響應的狀態值. 完整的狀態取值可參見 W3C site. 我們著重看值為200 OK的響應.

i f (http_request.status == 200) {
??? // perfect!
} else {
??? // there was a problem with the request,
??? // for example the response may be a 404 (Not Found)
??? // or 500 (Internal Server Error) response codes
}

  在檢查完請求的狀態值和響應的HTTP狀態值后, 您就可以處理從服務器得到的數據了.有兩種方式可以得到這些數據:

??http_request.responseText – 以文本字符串的方式返回服務器的響應
??http_request.responseXML – 以XMLDocument對象方式返回響應.處理XMLDocument對象可以用JavaScript DOM函數

  步驟 3 – "萬事俱備!" - 簡單實例

  我們現在將整個過程完整地做一次,發送一個簡單的HTTP請求. 我們用JavaScript請求一個HTML文件, test.html, 文件的文本內容為"I'm a test.".然后我們"alert()"test.html文件的內容.

<script type="text/javascript" language="javascript">

??? var http_request = false;

??? function makeRequest(url) {

??????? http_request = false;

??????? if (window.XMLHttpRequest) { // Mozilla, Safari,...
??????????? http_request = new XMLHttpRequest();
??????????? if (http_request.overrideMimeType) {
??????????????? 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) {
??????????? alert('Giving up :( Cannot create an XMLHTTP instance');
??????????? return false;
??????? }
??????? http_request.onreadystatechange = alertContents;
??????? http_request.open('GET', url, true);
??????? http_request.send(null);

??? }

??? function alertContents() {

??????? if (http_request.readyState == 4) {
??????????? if (http_request.status == 200) {
??????????????? alert(http_request.responseText);
??????????? } else {
??????????????? alert('There was a problem with the request.');
??????????? }
??????? }

??? }
</script>
<span
??? style="cursor: pointer; text-decoration: underline"
??? onclick="makeRequest('test.html')">
??????? Make a request
</span>

  本例中:

??用戶點擊瀏覽器上的"請求"鏈接;
??接著函數makeRequest()將被調用.其參數 – HTML文件test.html在同一目錄下;
??這樣就發起了一個請求.onreadystatechange的執行結果會被傳送給alertContents();
??alertContents()將檢查服務器的響應是否成功地收到,如果是,就會"alert()"test.html文件的內容.?

  步驟 4 – "X-文檔" --- 處理XML響應

  在前面的例子中,當服務器對HTTP請求的響應被收到后,我們會調用請求對象的reponseText屬性.該屬性包含了test.html文件的內容.現在我們來試試responseXML屬性.

  首先,我們新建一個有效的XML文件,后面我們將使用這個文件.該文件(test.xml)源代碼如下所示:

<?xml version="1.0" ?>
<root>
??? I'm a test.
</root>

  在該腳本中,我們只需修改請求部分:
...
onclick="makeRequest('test.xml')">
...

  接著,在alertContents()中,我們將alert()的代碼alert(http_request.responseText);換成:

var xmldoc = http_request.responseXML;
var root_node = xmldoc.getElementsByTagName('root').item(0);
alert(root_node.firstChild.data);

  這里,我們使用了responseXML提供的XMLDocument對象并用DOM方法獲取存于XML文件中的內容.



kelven 2006-05-23 09:23 發表評論
]]>
用AJAX開發智能Web應用程序之基礎篇http://www.aygfsteel.com/zhangrenquan/articles/39203.htmlkelvenkelvenTue, 04 Apr 2006 09:04:00 GMThttp://www.aygfsteel.com/zhangrenquan/articles/39203.htmlhttp://www.aygfsteel.com/zhangrenquan/comments/39203.htmlhttp://www.aygfsteel.com/zhangrenquan/articles/39203.html#Feedback0http://www.aygfsteel.com/zhangrenquan/comments/commentRss/39203.htmlhttp://www.aygfsteel.com/zhangrenquan/services/trackbacks/39203.html 一. 什么是AJAX?

  這個名字代表了異步JavaScript+XMLHTTPRequest,并且意味著你可以在基于瀏覽器的JavaScript和服務器之間建立套接字通訊。其實AJAX并不是一種新技術,而是已經成功地用于現代瀏覽器中的若干成功技術的可能性組合。所有的AJAX應用程序實現了一種“豐富的”UI——這是通過JavaScript操作HTML文檔對象模型并且經由XMLHttpRequest實現的精確定位的數據檢索來實現的。典型的示例AJAX應用程序是Google Labs(http://labs.google.com)的Google Maps和Google Suggest。這些應用程序現場監視用戶輸入并且提供實時的頁面更新。最重要的是,在用戶通過地圖導航或輸入一個查找字符串的同時,這些事件不需要刷新頁面。

  事實上,支持這些令人感到驚訝的應用的技術已經出現一段時間了,盡管它們要求復雜的技能以及使用瀏覽器的技巧。一些專利產品就提供了相似的能力——如Macromedia Flash插件,Java Applets或.NET運行時——在達到實用上已經有一段時間了。把一種可與服務器通話的腳本組件引入到瀏覽器中的思想早在IE 5.0中就已經存在。Firefox和其它流行的瀏覽器也加入到瀏覽器大軍中并以一種內置對象形式支持XMLHTTPRequest。隨著跨平臺瀏覽器的出現,這些技術得到了認可并在2004年3月一家稱為Adaptive Path的公司中正式提出了AJAX。

  簡而言之,由于來自于Google的支持和安裝了一點可用的瀏覽器技術,加上為了一種"更好的用戶體驗",每個人都在把客戶端技術添加到Web應用程序上。

  二. AJAX與傳統應用程序的區別

  一個傳統Web應用程序模型實際上是一種基本的事件——用戶被迫提交表單以實現頁面交換。也就是說,表單提交和頁面傳送無法得到保證:還有更壞的情形——用戶需要再次點擊。這與AJAX截然不同-——數據跨過線路而不是完整的HTML頁面傳輸。這種數據交換是經由特定的瀏覽器對象:XMLHttpRequest實現的;再由適當的邏輯來處理每個數據請求的結果,頁面的特定區域而不是完整的頁面被更新。結果是更快的速度,更少的擁擠和更好的信息傳送控制。

  傳統型"click-refresh"Web應用程序強迫用戶中斷工作過程而等待頁面的重裝。通過引入AJAX技術,一個客戶端腳本能夠異步地與服務器通話,而用戶仍能保持輸入數據。除了對用戶透明之外,這樣的異步意味著服務器可以有更多時間來處理請求。

  傳統Web應用程序把所有的處理代理到服務器并且強迫服務器進行狀態管理。AJAX允許靈活劃分應用程序邏輯以及客戶和服務器之間的狀態管理。這就消除了一種"click-refresh"依賴性并且提供更好的服務器可伸縮性。當該狀態存儲在客戶端,你就不必跨越服務器來維持會話或保存/結束狀態-其使用期限是由客戶端來定義的。

  三. AJAX——分布式的MVC

  盡管AJAX應用程序依靠JavaScript來實現描述層,然而處理能力和知識庫仍然存在于服務器上。此時,AJAX應用程序大量的與J2EE服務器通訊——把數據輸入/輸出Web服務和servlets。具有基于AJAX的描述層的J2EE應用程序和標準J2EE應用程序之間的區別首先在于,MVC是通過線路分布的。通過使用AJAX,視圖是本地的,而模型和控制器是分布式的——這使得開發者能夠靈活地決定哪些部件會是基于客戶端的。具體地說,本地視圖通過巧妙地操作HTML DOM而生成圖形;控制器局部地處理用戶輸入并且根據開發者的判斷擴展到服務器的處理——經由HTTP請求(Web服務,XML/RPC或其它)實現;模型的遠程部分是根據客戶端需要而下載的以達到實時更新客戶端頁面;并且狀態是在客戶端收集的。

  在以后的AJAX文章中,我們將比較深入地討論這里的每一種組件并提供有關它們聯合在一起進行應用的示例。現在,先不多說,讓我們詳細地分析一個簡單的AJAX示例。

  四. 郵政區號校驗和查詢

  我們將創建一個包含三個INPUT字段(Zip,City和State)的HTML頁面。我們將保證,只要用戶輸入郵政區號的前三個數字,該頁面上的字段就會用第一個匹配的狀態值填充。一旦用戶輸入了所有五位郵政區號數,我們將立即決定和填充相應的城市。如果郵政區號無效(在服務器的數據庫沒有找到),那么我們將把郵政區號的邊界設置為紅色。這樣的可視化線索有助于用戶并且在現代瀏覽器中已經成為一種標準(作為一實例,當Firefox找到一個HTML頁面中的匹配關鍵字時,它會高亮與你在瀏覽器查找域輸入的內容一致的部分)。

  讓我們首先創建一個簡單的包含三個INPUT字段的HTML:zip,city和state。請注意,一旦一個字符輸入進郵政區號字段域中,即調用方法zipChanged()。JavaScript函數zipChanged()(見下)在當zip長度為3時調用函數updateState(),而在當zip長度為5時調用函數up-dateCity()。而updateCity()和updateState()把大部分的工作代理到另一個函數ask()。

Zip:<input id="zipcode" type="text" maxlength="5" onKeyUp="zipChanged()"
style="width:60"/>
City: <input id="city" disabled maxlength="32" style="width:160"/>
State:<input id="state" disabled maxlength="2" style="width:30"/>
<script src="xmlhttp.js"></script>
<script>
var zipField = null;
function zipChanged(){
zipField = document.getElementById("zipcode")
var zip = zipField.value;
zip.length == 3?updateState(zip):zip.length == 5?updateCity(zip):"";
}
function updateState(zip) {
 var stateField = document.getElementById("state");
 ask("resolveZip.jsp?lookupType=state&zip="+zip, stateField, zipField);
}
function updateCity(zip) {
 var cityField = document.getElementById("city");
 ask("resolveZip.jsp? lookupType=city&zip="+zip, cityField, zipField);
}
</script>


??? 函數ask()與服務器進行通訊并分配一個回調函數來處理服務器的響應(見下列代碼)。后面,我們將分析具有雙重特點的resolveZip.jsp的內容-它根據zip字段中的字符數查找city或state信息。重要的是,ask()使用了具有異步特點的XmlHttpRequest,這樣填充state和city字段或著色zip字段邊界就可以不必減慢數據入口而得以實現。首先,我們調用request.open()-它用服務器打開套接字頻道,使用一個HTTP動詞(GET或POST)作為第一個參數并且以數據提供者的URL作為第二個參數。request.open()的最后一個參數被設置為true-它指示該請求的異步特性。注意,該請求還沒有被提交。隨著對request.send()的調用,開始提交-這可以為POST提供任何必要的有效載荷。在使用異步請求時,我們必須使用request.onreadystatechanged屬性來分配請求的回調函數。(如果請求是同步的話,我們應該能夠在調用request.send之后立即處理結果,但是我們也有可能阻斷用戶,直到該請求完成為止。)

HTTPRequest = function () {
 var xmlhttp=null;
 try {
  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (_e) {
  try {
   xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (_E) { }
 }
 if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
  try {
   xmlhttp = new XMLHttpRequest();
  } catch (e) {
   xmlhttp = false;
  }
 }
 return xmlhttp;
}

function ask(url, fieldToFill, lookupField) {
 var http = new HTTPRequest();
 http.open("GET", url, true);
 http.onreadystatechange = function (){ handleHttpResponse(http, fieldToFill,lookupField)};
 http.send(null);
}

function handleHttpResponse(http, fieldToFill, lookupField) {
 if (http.readyState == 4) {
  result = http.responseText;
  if ( -1 != result.search("null") ) {
   lookupField.style.borderColor = "red";
   fieldToFill.value = "";
  } else {
   lookupField.style.borderColor = "";
   fieldToFill.value = result;
  }
 }
}

  為ask()所使用的HttpRequest()函數(見上)是一跨瀏覽器的XMLHTTPRequest的一個實例的構造器;稍后我們將分析它。到目前為止,請注意對于handleResponse()的調用是如何用一匿名函數包裝的-這個函數是function(){handleHttpResponse(http,fieldToFill, lookupField)}。

  該函數的代碼是動態創建的并且在每次我們給http.onreadstatechange屬性賦值時被編譯。結果,JavaScript創建一個指向上下文(所有的變量都可以存取正在結束的方法-ask())的指針。這樣以來,匿名函數和handleResponse()就能夠被保證充分存取所有的上下文宿主的變量,直至到匿名函數的參考被垃圾回收站收集為止。換句話說,無論何時我們的匿名函數被調用,它都能無縫地參考request,fieldToFill和lookupField變量,就象它們是全局的一樣。而且,每次ask()調用都將創建環境的一個獨立拷貝,并且此時這些變量中保存有該函數將結束時的值。

  現在,讓我們分析一下函數handleResponse()。既然它能夠在請求處理的不同狀態下激活,那么該函數將忽略所有的情形-除了該請求處理完成之外-這相應于request.readyState屬性等于4("Completed")。此時,該函數讀取服務器的響應文本。與它的名字所暗示的相反,XmlHttpRequest的輸入和輸出都不必限于XML格式。特別地,我們的resolveZip.jsp(見源碼中的列表1)返回普通文本。如果返回值為"unknown",那么該函數將假定郵政區號是無效的并且把查找字段(zip)邊界顏色置為紅色。否則,返回值被用于填充字段state或city,并且zip的邊界被賦予一種缺省顏色。

XMLHttpRequest-傳輸對象

  讓我們返回到我們的XMLHTTPRequest的跨瀏覽器實現。最后一個列表包含一個HttpRequest()函數-它向上兼容于IE5.0和Mozilla 1.8/FireFox。為簡化起見,我們只創建一個微軟XMLHTTPRequest對象,而且如果創建失敗,我們假定它是Firefox/Mozilla。

  該函數的核心是XMLHTTPRequest-這是一個本機瀏覽器對象,它為包括HTTP協議的任何東西與服務器之間的通訊提供方便。它允許指定任何HTTP動詞,頭部和有效載荷,并且能夠以異步或同步方式工作。不需要下載也不需要安裝任何插件-盡管在IE的情形下,XMLHTTPRequest是一個集成到瀏覽器內部的ActiveX。因而,"Run ActiveX Control and Plugins"默認IE權限應該正好適合使用它。

  最重要的是,XMLHTTPRequest允許一個到服務器的RPC風格的編程查詢而不需要任何頁面刷新。它以一種可預測的,可控制的方式來實現此-提供了到HTTP協議的所有細節的完整存取-包括頭部和數據的任何定制格式。在以后的文章中,我們將向你展示其它一些業界協議-你可以在這些傳輸協議(如Web服務和XML-RPC)之上運行-它們極大地簡化大規模應用程序的開發和維護。

  五.服務器端邏輯

  最后,服務器端的resolveZip.jsp被從函數ask()中調用(見所附源碼中的列表1)。這個resolveZip.jsp在兩種由當前的郵政區號長度所區分的獨立的場所下被調用(見zipChanged()函數)。請求參數lookupType的值或者是state或者是city。為簡化起見,我們將假定,兩個文件state.properties和city.properties都位于服務器中C驅動器的根目錄下。resolveZip.jsp邏輯負責用適當的預裝載的文件返回查找值。

  我們的支持AJAX的頁面現在已經準備好了。

  六.遠程腳本技術-一種可選方法

  一些更舊的AJAX實現是基于所謂的遠程腳本技術。這種思想是,用戶的行為導致經由IFRAME對服務器進行查詢,而服務器用JavaScript作出響應,該腳本一旦到達客戶端立即被執行。這與XMLHttpRequest方法相比存在較大的區別,在后者情況下,服務器響應數據而客戶端解釋數據。其好處是這種解決方案支持更舊的瀏覽器。

  基于IFRAME示例的HTML部分(見所附源碼中的列表2)與我們在XMLHTTPRequest場合下所用的極相似,但是這次我們將引入另外一個IFRAME元素-controller:

Zip:<input id="zipcode" type="text" maxlength="5" onKeyUp="zipChanged()"
style="width:60" size="20"/>
City: <input id="city" disabled maxlength="32" style="width:160" size="20"/>
State:<input id="state" disabled maxlength="2" style="width:30" size="20"/>
<iframe id="controller" style="visibility:hidden;width:0;height:0"></iframe>

  我們保持每次擊鍵都調用zipChanged()一次,但是這一次,從zipChanged()中被調用的函數ask()(見所附源碼中的列表3)負責設置IFRAME的src屬性,而不是調用一個XMLHTTPRequest:

function ask(url, fieldToFill, lookupField){
 var controller = document.getElementById("controller");
 controller.src= url+"&field="+fieldToFill.id+"&zip="+lookupField.id;
}

  服務器端邏輯由一個粗略的resolveZip.jsp(見所附源碼中的列表4)所描述。它與它的XMLHTTPRequest對應物相區別-它返回JavaScript語句,這些語句設置變量字段lookup和city的全局值,而且一旦它到達瀏覽器即從全局窗口的執行上下文中調用函數response()。

  函數response()是一修改版本的handleResponse()-這一函數可以免于處理未完成的請求(詳見本文所附源碼中的列表2)。

  七. 難題

  為簡化起見,讓我們"俯看"一下在我們的示例代碼中的一些重要的問題:

  1.事實-XMLHTTPRequest對象實例和回調函數調用在被使用以后并沒被破壞-在每次調用后這有可能導致內存泄漏。適當編寫的代碼應該破壞或重用對象池中的這些實例。而且,客戶端必須使用與服務器軟件相同的對象管理技術。

  2.在大多數情況下,錯誤往往得不到有效處理。例如,在方法ask()中對request.open()的調用可能引發一個異常,這是必須要捕獲和處理的,即使在瀏覽器中沒有設置JavaScript異常自動捕獲功能。而handleResponse()函數又是另外一個例子。它必須要為可能的服務器端和通訊錯誤而檢查headers和responseText值。在發生錯誤的情況下,它必須盡力恢復并/或者報告錯誤。正確開發的AJAX應用程序要盡可能避免"提交"松散的數據,因為往往存在線路斷開和其它低級通訊的問題-所以這些程序必須建立一個強壯的和自恢復的框架為此提供支持。

  3.當前服務器端框架提供相當多的功能-它們可以與一種自由刷新方法和諧相處。例如,讓我們考慮一個定制的在指定時間內的服務器端認證的問題。在這種情況下,我們必須攔截到XMLHTTPRequest調用的安全系統響應,顯示登錄屏幕,然后在用戶被認證后重新發出請求。

  所有的這些問題只是一些典型的用低級API工作的任何應用程序代碼,而且所有這些問題都能被解決。好消息是,解決這些問題所需要的技術十分相似于大多數Java開發技術,如Web服務,定制標簽和XML/XSLT。唯一的區別在于,現在這些技術以下列形式用于客戶端:

  ·Web服務-使用SOAP/REST/RPC等簡單通訊標準

  ·客戶端定制標簽-打包豐富的客戶端控件并集成AJAX功能

  ·數據操作-基于XML和基于XSLT技術

  八. 小結

  AJAX方法能夠向人們提供一種與桌面應用程序相同的豐富的互聯網體驗。但是,我們必須有選擇地使用AJAX技術,如當你仍在線購物時,你絕對不想讓你的信用卡通過后臺處理就悄悄地開始付款。AJAX會成為一種持續的動力嗎?我們當然希望這樣。在過去的五年時間內我們一直在努力開發AJAX應用程序并且能證明它是健全并且很有效的。然而,它要求一個開發者必須精通大量技術而不是在傳統的"click-refresh"Web應用程序中所使用的那些。



kelven 2006-04-04 17:04 發表評論
]]>
舉例學習ajaxhttp://www.aygfsteel.com/zhangrenquan/articles/39202.htmlkelvenkelvenTue, 04 Apr 2006 09:02:00 GMThttp://www.aygfsteel.com/zhangrenquan/articles/39202.htmlhttp://www.aygfsteel.com/zhangrenquan/comments/39202.htmlhttp://www.aygfsteel.com/zhangrenquan/articles/39202.html#Feedback0http://www.aygfsteel.com/zhangrenquan/comments/commentRss/39202.htmlhttp://www.aygfsteel.com/zhangrenquan/services/trackbacks/39202.html示例一:該示例返回每個Node 的value.

<html>
<body>
<script type="text/vbscript">

set xmlDoc=CreateObject("Microsoft.XMLDOM")
xmlDoc.async="false"
xmlDoc.load("note.xml")

for each x in xmlDoc.documentElement.childNodes
?document.write(x.childnodes(0).nodeValue & "<br />")
next
</script>
</body>
</html

準備一個note.xml文件,很簡單幾行:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited with XML Spy v4.2 -->
<note time="12:03:46">
? <to>Tove</to>
? <from>Jani</from>
? <heading>Reminder</heading>
? <body>Don't forget me this weekend!</body>
</note>

示例二:創建一個XMLHttpRequest.

<html>
<head>
<script type="text/javascript">
var xmlhttp

function loadXMLDoc(url)
{
// code for Mozilla, etc.
if (window.XMLHttpRequest)
? {
? xmlhttp=new XMLHttpRequest()
? xmlhttp.onreadystatechange=state_Change
? xmlhttp.open("GET",url,true)
? xmlhttp.send(null)
? }
// code for IE
else if (window.ActiveXObject)
? {
? xmlhttp=new ActiveXObject("Microsoft.XMLHTTP")
??? if (xmlhttp)
??? {
??? xmlhttp.onreadystatechange=state_Change
??? xmlhttp.open("GET",url,true)
??? xmlhttp.send()
??? }
? }
}

function state_Change()
{
// if xmlhttp shows "loaded"
if (xmlhttp.readyState==4)
? {
? // if "OK"
? if (xmlhttp.status==200)
? {
? alert("XML data OK")
? document.getElementById('A1').innerHTML=xmlhttp.status
? document.getElementById('A2').innerHTML=xmlhttp.statusText
? document.getElementById('A3').innerHTML=xmlhttp.responseText
? }
? else
? {
? alert("Problem retrieving XML data:" + xmlhttp.statusText)
? }
? }
}

</script>
</head>

<body script_onload="loadXMLDoc('note.xml')">
<h2>Using the HttpRequest Object</h2>

<p><b>status:</b>
<span id="A1"></span>
</p>

<p><b>status text:</b>
<span id="A2"></span>
</p>

<p><b>response:</b>
<br><span id="A3"></span>
</p>

</body>
</html>
對著代碼 和運行結果看,很容易熟悉XMLHttpRequest對象.

function loadXMLDoc(url)中根據不同的客戶端創建XMLHttpRequest對象,然后對傳入的url向Server發送GET請求,true參數是為了表明要異步請求.完了之后 ,state_Change()被調用,該方法就是得到Server返回的狀態.并傳給網頁顯示出來.



kelven 2006-04-04 17:02 發表評論
]]>
掌握 ajax,第 1 部分: ajax 簡介 (轉載)http://www.aygfsteel.com/zhangrenquan/articles/39198.htmlkelvenkelvenTue, 04 Apr 2006 08:46:00 GMThttp://www.aygfsteel.com/zhangrenquan/articles/39198.htmlhttp://www.aygfsteel.com/zhangrenquan/comments/39198.htmlhttp://www.aygfsteel.com/zhangrenquan/articles/39198.html#Feedback0http://www.aygfsteel.com/zhangrenquan/comments/commentRss/39198.htmlhttp://www.aygfsteel.com/zhangrenquan/services/trackbacks/39198.html?????????五年前,如果不知道 xml,您就是一只無人重視的丑小鴨。十八個月前,ruby 成了關注的中心,不知道 ruby 的程序員只能坐冷板凳了。今天,如果想跟上最新的技術時尚,那您的目標就是 ajax。

  但是,ajax 不僅僅是一種時尚,它是一種構建網站的強大方法,而且不像學習一種全新的語言那樣困難。

  但在詳細探討 ajax 是什么之前,先讓我們花幾分鐘了解 ajax 做什么。目前,編寫應用程序時有兩種基本的選擇:

  桌面應用程序,web 應用程序。兩者是類似的,桌面應用程序通常以 cd 為介質(有時候可從網站下載)并完全安裝到您的計算機上。桌面應用程序可能使用互聯網下載更新,但運行這些應用程序的代碼在桌面計算機上。web 應用程序運行在某處的 web 服務器上 —— 毫不奇怪,要通過 web 瀏覽器訪問這種應用程序。

  不過,比這些應用程序的運行代碼放在何處更重要的是,應用程序如何運轉以及如何與其進行交互。桌面應用程序一般很快(就在您的計算機上運行,不用等待互聯網連接),具有漂亮的用戶界面(通常和操作系統有關)和非凡的動態性??梢詥螕?、選擇、輸入、打開菜單和子菜單、到處巡游,基本上不需要等待。

  另一方面,web 應用程序是最新的潮流,它們提供了在桌面上不能實現的服務(比如 amazon.com 和 ebay)。但是,伴隨著 web 的強大而出現的是等待,等待服務器響應,等待屏幕刷新,等待請求返回和生成新的頁面。

  顯然這樣說過于簡略了,但基本的概念就是如此。您可能已經猜到,ajax 嘗試建立桌面應用程序的功能和交互性,與不斷更新的 web 應用程序之間的橋梁??梢允褂孟褡烂鎽贸绦蛑谐R姷膭討B用戶界面和漂亮的控件,不過是在 web 應用程序中。

  還等什么呢?我們來看看 ajax 如何將笨拙的 web 界面轉化成能迅速響應的 ajax 應用程序吧。

  老技術,新技巧

  在談到 ajax 時,實際上涉及到多種技術,要靈活地運用它必須深入了解這些不同的技術(本系列的頭幾篇文章將分別討論這些技術)。好消息是您可能已經非常熟悉其中的大部分技術,更好的是這些技術都很容易學習,并不像完整的編程語言(如 java 或 ruby)那樣困難。

  ajax 的定義

  順便說一下,ajax 是 asynchronous javascript and xml(以及 dhtml 等)的縮寫。這個短語是 adaptive path 的 jesse james garrett 發明的,按照 jesse 的解釋,這不是個首字母縮寫詞。

  下面是 ajax 應用程序所用到的基本技術:

html 用于建立 web 表單并確定應用程序其他部分使用的字段。
javascript 代碼是運行 ajax 應用程序的核心代碼,幫助改進與服務器應用程序的通信。
dhtml 或 dynamic html,用于動態更新表單。我們將使用div、span和其他動態 html 元素來標記 html。
文檔對象模型 dom 用于(通過 javascript 代碼)處理 html 結構和(某些情況下)服務器返回的 xml。

  我們來進一步分析這些技術的職責。以后的文章中我將深入討論這些技術,目前只要熟悉這些組件和技術就可以了。對這些代碼越熟悉,就越容易從對這些技術的零散了解轉變到真正把握這些技術(同時也真正打開了 web 應用程序開發的大門)。

  xmlhttprequest 對象

  要了解的一個對象可能對您來說也是最陌生的,即xmlhttprequest。這是一個 javascript 對象,創建該對象很簡單,如清單 1 所示。

  清單 1. 創建新的 xmlhttprequest 對象

<script language="javascript" type="text/javascript">
var xmlhttp = new xmlhttprequest();
</script>

  下一期文章中將進一步討論這個對象,現在要知道這是處理所有服務器通信的對象。繼續閱讀之前,先停下來想一想:通過xmlhttprequest對象與服務器進行對話的是 javascript 技術。這不是一般的應用程序流,這恰恰是 ajax 的強大功能的來源。

  在一般的 web 應用程序中,用戶填寫表單字段并單擊 submit 按鈕。然后整個表單發送到服務器,服務器將它轉發給處理表單的腳本(通常是 php 或 java,也可能是 cgi 進程或者類似的東西),腳本執行完成后再發送回全新的頁面。該頁面可能是帶有已經填充某些數據的新表單的 html,也可能是確認頁面,或者是具有根據原來表單中輸入數據選擇的某些選項的頁面。當然,在服務器上的腳本或程序處理和返回新表單時用戶必須等待。屏幕變成一片空白,等到服務器返回數據后再重新繪制。這就是交互性差的原因,用戶得不到立即反饋,因此感覺不同于桌面應用程序。

  ajax 基本上就是把 javascript 技術和xmlhttprequest對象放在 web 表單和服務器之間。當用戶填寫表單時,數據發送給一些 javascript 代碼而不是直接發送給服務器。相反,javascript 代碼捕獲表單數據并向服務器發送請求。同時用戶屏幕上的表單也不會閃爍、消失或延遲。換句話說,javascript 代碼在幕后發送請求,用戶甚至不知道請求的發出。更好的是,請求是異步發送的,就是說 javascript 代碼(和用戶)不用等待服務器的響應。因此用戶可以繼續輸入數據、滾動屏幕和使用應用程序。

  然后,服務器將數據返回 javascript 代碼(仍然在 web 表單中),后者決定如何處理這些數據。它可以迅速更新表單數據,讓人感覺應用程序是立即完成的,表單沒有提交或刷新而用戶得到了新數據。javascript 代碼甚至可以對收到的數據執行某種計算,再發送另一個請求,完全不需要用戶干預!這就是xmlhttprequest的強大之處。它可以根據需要自行與服務器進行交互,用戶甚至可以完全不知道幕后發生的一切。結果就是類似于桌面應用程序的動態、快速響應、高交互性的體驗,但是背后又擁有互聯網的全部強大力量。

  加入一些 javascript

  得到xmlhttprequest的句柄后,其他的 javascript 代碼就非常簡單了。事實上,我們將使用 javascript 代碼完成非?;镜娜蝿眨?/p>

獲取表單數據:javascript 代碼很容易從 html 表單中抽取數據并發送到服務器。
修改表單上的數據:更新表單也很簡單,從設置字段值到迅速替換圖像。
解析 html 和 xml:使用 javascript 代碼操縱 dom(請參閱 下一節),處理 html 表單服務器返回的 xml 數據的結構。

  對于前兩點,需要非常熟悉getelementbyid()方法,如清單 2 所示。

  清單 2. 用 javascript 代碼捕獲和設置字段值

/ 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];

  這里沒有特別需要注意的地方,真是好極了!您應該認識到這里并沒有非常復雜的東西。只要掌握了xmlhttprequest,ajax 應用程序的其他部分就是如清單 2 所示的簡單 javascript 代碼了,混合有少量的 html。同時,還要用一點兒 dom,我們就來看看吧。

  以 dom 結束

  最后還有 dom,即文檔對象模型??赡軐τ行┳x者來說 dom 有點兒令人生畏,html 設計者很少使用它,即使 javascript 程序員也不大用到它,除非要完成某項高端編程任務。大量使用 dom 的是復雜的 java 和 c/c++ 程序,這可能就是 dom 被認為難以學習的原因。

  幸運的是,在 javascript 技術中使用 dom 很容易,也非常直觀。現在,按照常規也許應該說明如何使用 dom,或者至少要給出一些示例代碼,但這樣做也可能誤導您。即使不理會 dom,仍然能深入地探討 ajax,這也是我準備采用的方法。以后的文章將再次討論 dom,現在只要知道可能需要 dom 就可以了。當需要在 javascript 代碼和服務器之間傳遞 xml 和改變 html 表單的時候,我們再深入研究 dom。沒有它也能做一些有趣的工作,因此現在就把 dom 放到一邊吧。

  獲取 request 對象

  有了上面的基礎知識后,我們來看看一些具體的例子。xmlhttprequest是 ajax 應用程序的核心,而且對很多讀者來說可能還比較陌生,我們就從這里開始吧。從清單 1 可以看出,創建和使用這個對象非常簡單,不是嗎?等一等。

  還記得幾年前的那些討厭的瀏覽器戰爭嗎?沒有一樣東西在不同的瀏覽器上得到同樣的結果。不管您是否相信,這些戰爭仍然在繼續,雖然規模較小。但令人奇怪的是,xmlhttprequest成了這場戰爭的犧牲品之一。因此獲得xmlhttprequest對象可能需要采用不同的方法。下面我將詳細地進行解釋。

  使用 microsoft 瀏覽器

  microsoft 瀏覽器 internet explorer 使用 msxml 解析器處理 xml(可以通過參考資料進一步了解 msxml)。因此如果編寫的 ajax 應用程序要和 internet explorer 打交道,那么必須用一種特殊的方式創建對象。

  但并不是這么簡單。根據 internet explorer 中安裝的 javascript 技術版本不同,msxml 實際上有兩種不同的版本,因此必須對這兩種情況分別編寫代碼。請參閱清單 3,其中的代碼在 microsoft 瀏覽器上創建了一個xmlhttprequest。

  清單 3. 在 microsoft 瀏覽器上創建 xmlhttprequest 對象

var xmlhttp = false;
try {
?xmlhttp = new activexobject("msxml2.xmlhttp");
} catch (e) {
?try {
??? xmlhttp = new activexobject("microsoft.xmlhttp");
?} catch (e2) {
??? xmlhttp = false;
?}
}

  您對這些代碼可能還不完全理解,但沒有關系。當本系列文章結束的時候,您將對 javascript 編程、錯誤處理、條件編譯等有更深的了解?,F在只要牢牢記住其中的兩行代碼:

xmlhttp = new activexobject("msxml2.xmlhttp");

 和

xmlhttp = new activexobject("microsoft.xmlhttp");。

  這兩行代碼基本上就是嘗試使用一個版本的 msxml 創建對象,如果失敗則使用另一個版本創建該對象。不錯吧?如果都不成功,則將xmlhttp變量設為 false,告訴您的代碼出現了問題。如果出現這種情況,可能是因為安裝了非 microsoft 瀏覽器,需要使用不同的代碼。

  處理 mozilla 和非 microsoft 瀏覽器

  如果選擇的瀏覽器不是 internet explorer,或者為非 microsoft 瀏覽器編寫代碼,就需要使用不同的代碼。事實上就是清單 1 所示的一行簡單代碼:

var xmlhttp = new xmlhttprequest object;。

  這行簡單得多的代碼在 mozilla、firefox、safari、opera 以及基本上所有以任何形式或方式支持 ajax 的非 microsoft 瀏覽器中,創建了xmlhttprequest對象。

  結合起來

  關鍵是要支持所有瀏覽器。誰愿意編寫一個只能用于 internet explorer 或者非 microsoft 瀏覽器的應用程序呢?或者更糟,要編寫一個應用程序兩次?當然不!因此代碼要同時支持 internet explorer 和非 microsoft 瀏覽器。清單 4 顯示了這樣的代碼。

  清單 4. 以支持多種瀏覽器的方式創建 xmlhttprequest 對象

/* create a new xmlhttprequest object to talk to the web server */
var xmlhttp = false;
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
try {
?xmlhttp = new activexobject("msxml2.xmlhttp");
} catch (e) {
?try {
??? xmlhttp = new activexobject("microsoft.xmlhttp");
?} catch (e2) {
??? xmlhttp = false;
?}
}
@end @*/
?
if (!xmlhttp && typeof xmlhttprequest != 'undefined') {
?xmlhttp = new xmlhttprequest();
}

  現在先不管那些注釋掉的奇怪符號,如@cc_on,這是特殊的 javascript 編譯器命令,將在下一期針對xmlhttprequest的文章中詳細討論。這段代碼的核心分為三步:

  1.?????? 建立一個變量xmlhttp來引用即將創建的xmlhttprequest對象。
  2.?????? 嘗試在 microsoft 瀏覽器中創建該對象:
  o??????? 嘗試使用msxml2.xmlhttp對象創建它。
  o??????? 如果失敗,再嘗試microsoft.xmlhttp對象。
  3.?????? 如果仍然沒有建立xmlhttp,則以非 microsoft 的方式創建該對象。

  最后,xmlhttp應該引用一個有效的xmlhttprequest對象,無論運行什么樣的瀏覽器。

  關于安全性的一點說明

  安全性如何呢?現在瀏覽器允許用戶提高他們的安全等級,關閉 javascript 技術,禁用瀏覽器中的任何選項。在這種情況下,代碼無論如何都不會工作。此時必須適當地處理問題,這需要單獨的一篇文章來討論,要放到以后了(這個系列夠長了吧?不用擔心,讀完之前也許您就掌握了)?,F在要編寫一段健壯但不夠完美的代碼,對于掌握 ajax 來說就很好了。以后我們還將討論更多的細節。

  ajax 世界中的請求/響應

  現在我們介紹了 ajax,對xmlhttprequest對象以及如何創建它也有了基本的了解。如果閱讀得很仔細,您可能已經知道與服務器上的 web 應用程序打交道的是 javascript 技術,而不是直接提交給那個應用程序的 html 表單。

  還缺少什么呢?到底如何使用xmlhttprequest。因為這段代碼非常重要,您編寫的每個 ajax 應用程序都要以某種形式使用它,先看看 ajax 的基本請求/響應模型是什么樣吧。

  發出請求

  您已經有了一個嶄新的xmlhttprequest對象,現在讓它干點活兒吧。首先需要一個 web 頁面能夠調用的 javascript 方法(比如當用戶輸入文本或者從菜單中選擇一項時)。接下來就是在所有 ajax 應用程序中基本都雷同的流程:

1.?????? 從 web 表單中獲取需要的數據。
2.?????? 建立要連接的 url。
3.?????? 打開到服務器的連接。
4.?????? 設置服務器在完成后要運行的函數。
5.?????? 發送請求。

  清單 5 中的示例 ajax 方法就是按照這個順序組織的:

  清單 5. 發出 ajax 請求

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) + "&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);
}

  其中大部分代碼意義都很明確。開始的代碼使用基本 javascript 代碼獲取幾個表單字段的值。然后設置一個 php 腳本作為鏈接的目標。要注意腳本 url 的指定方式,city 和 state(來自表單)使用簡單的 get 參數附加在 url 之后。

  然后打開一個連接,這是您第一次看到使用xmlhttprequest。其中指定了連接方法(get)和要連接的 url。最后一個參數如果設為true,那么將請求一個異步連接(這就是 ajax 的由來)。如果使用false,那么代碼發出請求后將等待服務器返回的響應。如果設為true,當服務器在后臺處理請求的時候用戶仍然可以使用表單(甚至調用其他 javascript 方法)。

  xmlhttp(要記住,這是xmlhttprequest對象實例)的onreadystatechange屬性可以告訴服務器在運行完成后(可能要用五分鐘或者五個小時)做什么。因為代碼沒有等待服務器,必須讓服務器知道怎么做以便您能作出響應。在這個示例中,如果服務器處理完了請求,一個特殊的名為updatepage()的方法將被觸發。

  最后,使用值null調用send()。因為已經在請求 url 中添加了要發送給服務器的數據(city 和 state),所以請求中不需要發送任何數據。這樣就發出了請求,服務器按照您的要求工作。

  如果沒有發現任何新鮮的東西,您應該體會到這是多么簡單明了!除了牢牢記住 ajax 的異步特性外,這些內容都相當簡單。應該感激 ajax 使您能夠專心編寫漂亮的應用程序和界面,而不用擔心復雜的 http 請求/響應代碼。

  清單 5 中的代碼說明了 ajax 的易用性。數據是簡單的文本,可以作為請求 url 的一部分。用 get 而不是更復雜的 post 發送請求。沒有 xml 和要添加的內容頭部,請求體中沒有要發送的數據;換句話說,這就是 ajax 的烏托邦。

  不用擔心,隨著本系列文章的展開,事情會變得越來越復雜。您將看到如何發送 post 請求、如何設置請求頭部和內容類型、如何在消息中編碼 xml、如何增加請求的安全性,可以做的工作還有很多!暫時先不用管那些難點,掌握好基本的東西就行了,很快我們就會建立一整套的 ajax 工具庫。

  處理響應

  現在要面對服務器的響應了?,F在只要知道兩點:

  什么也不要做,直到xmlhttp.readystate屬性的值等于 4。 服務器將把響應填充到xmlhttp.responsetext屬性中。

  其中的第一點,即就緒狀態,將在下一篇文章中詳細討論,您將進一步了解 http 請求的階段,可能比您設想的還多。現在只要檢查一個特定的值(4)就可以了(下一期文章中還有更多的值要介紹)。第二點,使用xmlhttp.responsetext屬性獲得服務器的響應,這很簡單。清單 6 中的示例方法可供服務器根據清單 5 中發送的數據調用。

  清單 6. 處理服務器響應

function updatepage() {
?if (xmlhttp.readystate == 4) {
??? var response = xmlhttp.responsetext;
??? document.getelementbyid("zipcode").value = response;
?}
}

  這些代碼同樣既不難也不復雜。它等待服務器調用,如果是就緒狀態,則使用服務器返回的值(這里是用戶輸入的城市和州的 zip 編碼)設置另一個表單字段的值。于是包含 zip 編碼的zipcode字段突然出現了,而用戶沒有按任何按鈕!這就是前面所說的桌面應用程序的感覺??焖夙憫?、動態感受等等,這些都只因為有了小小的一段 ajax 代碼。

  細心的讀者可能注意到zipcode是一個普通的文本字段。一旦服務器返回 zip 編碼,updatepage()方法就用城市/州的 zip 編碼設置那個字段的值,用戶就可以改寫該值。這樣做有兩個原因:保持例子簡單,說明有時候可能希望用戶能夠修改服務器返回的數據。要記住這兩點,它們對于好的用戶界面設計來說很重要。

  連接 web 表單

  還有什么呢?實際上沒有多少了。一個 javascript 方法捕捉用戶輸入表單的信息并將其發送到服務器,另一個 javascript 方法監聽和處理響應,并在響應返回時設置字段的值。所有這些實際上都依賴于調用第一個 javascript 方法,它啟動了整個過程。最明顯的辦法是在 html 表單中增加一個按鈕,但這是 2001 年的辦法,您不這樣認為嗎?還是像清單 7 這樣利用 javascript 技術吧。

  清單 7. 啟動一個 ajax 過程

<form>
?<p>city: <input type="text" name="city" id="city" size="25"
?????? onchange="callserver();" /></p>
?<p>state: <input type="text" name="state" id="state" size="25"
?????? onchange="callserver();" /></p>
?<p>zip code: <input type="text" name="zipcode" id="city" size="5" /></p>
</form>

  如果感覺這像是一段相當普通的代碼,那就對了,正是如此!當用戶在 city 或 state 字段中輸入新的值時,callserver()方法就被觸發,于是 ajax 開始運行了。有點兒明白怎么回事了吧?好,就是如此!



kelven 2006-04-04 16:46 發表評論
]]>
AJAX學習資料http://www.aygfsteel.com/zhangrenquan/articles/39182.htmlkelvenkelvenTue, 04 Apr 2006 08:06:00 GMThttp://www.aygfsteel.com/zhangrenquan/articles/39182.htmlhttp://www.aygfsteel.com/zhangrenquan/comments/39182.htmlhttp://www.aygfsteel.com/zhangrenquan/articles/39182.html#Feedback0http://www.aygfsteel.com/zhangrenquan/comments/commentRss/39182.htmlhttp://www.aygfsteel.com/zhangrenquan/services/trackbacks/39182.html Thinking in AJAX(一)

AJAX - X眾所周知,異步交互JavaScript腳本XML封裝數據是AJAX的三大特征。其實,在實際應用中,不需要牢牢套死這三條大律,在我看來,AJAX - X,即去掉用XML封裝數據,也不失為一種好的設計思路,如果應用恰當,更顯輕盈步伐和巧妙思路。

一般讀取AJAX返回的XML結構的數據時使用XMLHttp的responseXML對象屬性,同時,XMLHttp也提供了另外一個屬性,即ResponseText,通過這個屬性,XMLHttp可以接受來自服務器的文本結構的字符串信息。去掉XML的AJAX可以使用ResponseText這個對象屬性,很靈活的操控返回數據的格式,可以自定義格式,比如我通常喜歡用c語言的那種文件流方式定義返回的字符串結構,有文件頭和具體的文件信息實體,文件頭分為狀態信息以及文件字符長度,我摒棄了文件字符長度的定義,規定死接受的ResponseTex字符串中的第一位為狀態碼,比如設定常量值0表示一起正常,非0的數字表示不正常,甚至有錯誤等。如果有非0值,程序自動取第二位起到257位(長度為256)的字符串組成為狀態信息,從258位開始到末尾的字符串就是服務器返回的正常結果信息。
substring(0,1)取狀態碼
substring(1,256)取服務器錯誤信息(錯誤信息不夠256位用空格補齊,取到數據后進行Trim處理)
substring(256,末尾)取服務器返回的數據信息
三次substring即完成了一個簡單但完整的交互工作。比起XML解析組件來說要快的多。

用ResponseText比封裝為XML處理數據快和簡單是一個原因,另一個原因是可操控性更大更靈活,打開Google Suggest,在搜索框輸入字符可以給你給出拼寫提示,Suggest就是應用了AJAX技術,不過它在從服務器返回數據時并沒有使用XML封裝,也沒有自定義ResponseText格式,而是直接將返回代碼組織成js腳本,通過瀏覽器返回后直接執行,如eval(XMLHttp.ResponseText)這樣的方式進行執行,http://www.google.com/complete/search?hl=en&js=true&qu=ajax 通過這個鏈接你可以看到Suggest利用AJAX得到的返回數據,此頁面是在Google Suggest的搜索框中輸入"AJAX"后得系統動態返回的數據。

sendRPCDone(frameElement, "ajax", new Array("ajax", "ajax amsterdam", "ajax fc", "ajax ontario", "ajax grips", "ajax football club", "ajax public library", "ajax football", "ajax soccer", "ajax pickering transit"), new Array("3,840,000 results", "502,000 results", "710,000 results", "275,000 results", "8,860 results", "573,000 results", "40,500 results", "454,000 results", "437,000 results", "10,700 results"), new Array(""));

瀏覽器段拿到這段代碼后直接eval就可以了,至于sendRPCDone這個函數,那當然得實現定義后并裝載到頁面中啦。XMLHttp這個名字以XML開頭,讓很多人禁錮了思想和創意,完全拋棄X,你也可以做出純AJAX的實例來。

當然,對于大型系統來講,為了保持數據接口的一致和整齊,還是用XML來傳遞更嚴謹更統一點,聽說微軟已經發起了重寫XML Parse組件的號召,估計下一個版本的XMLHttp還是DOMParser還是MSXML2.DOMDocument都會大大提高效率,減少資源占用的。

Thinking in AJAX(二) —— 基于AJAX的WEB設計

一、AJAX最值得稱贊的是異步交互,而不是無刷新

很多人都看好AJAX無刷新的技術,以至于認同AJAX就是用來做無刷新的。這個認識是錯誤的,什么是無刷新?無刷新就是頁面無需重載,那什么又是異步交互?異步交互就是一個簡單的多線程,當你在一個blog里看文章時,同時也可以利用AJAX進行無刷新的回復提交,看起來雖然也是無刷新,但這里最重要的是異步,即你能一邊看文章,一邊又能向服務器提交你的回復信息,利用好這個異步,才能算是掌握了AJAX的精髓。很多場合,無刷新是呈現給用戶的視覺體驗,而異步交互卻是默默無聞的工作在臺后,這種情況導致大多數人的錯誤理解了AJAX的權重之分。

二、推薦在WEB上輕量級的應用AJAX




著名的圖片存儲網站Flickr利用AJAX可謂出神入化。我之所以這么說,是因為我認為Flickr深知AJAX的利與弊,并且牢牢抓住自己的網站的功能特點,并沒有因AJAX而AJAX,而是架驅于技術至上,讓AJAX融于網站之中,為網站提供了更好的功能服務。如Flickr中無論是在多圖列表頁面還是單圖詳細頁面,修改圖片的標題和描述都應用了AJAX技術,讓用戶無需跳轉到單獨的編輯頁面中,編輯后單擊保存,亦使用了異步交互的方式進行數據提交,這時,頁面上顯示一個Loading字符外,其他部分不受任何影響,可謂太貼心的服務。

再如基于Tag的專業Blog搜索服務商Technorati也使用了AJAX,在搜索某個Tag時,頁面主導部分會即刻顯示所有Technorati數據庫中查詢到的數據條目,在左邊的側邊欄上會顯示兩個Loading圖標,過一會兒,這兩個Loading就會顯示具體的內容了,顯示的是此Tag相關的Flickr的圖片和書簽服務網站(Furl&del.icio.us)的鏈接,因為這兩部分內容是取自其他網站,如果由服務器統一先取得數據在一同顯示到頁面時,會受到網速影響而變慢,通過AJAX的異步交互方式首先立即顯示本地數據,然后由客戶端去和Flickr、Furl、del.icio.us打交道分別取得它們的數據,即節約了流量帶寬又不影響用戶訪問速度,可謂高明。

通過以上兩個國外成功應用AJAX的網站,我們發現他們都使用的是輕量級的AJAX,就是那種交互簡單,數據較少的操作。這也符合AJAX的本意,雖然像www.backbase.combindows都在RIA上有驚人的表現能力,但是速度慢、搜索引擎支持不好、開發難度大等毛病還是無法讓用戶滿意的,請記?。篈JAX的最終目的是為了提高用戶體驗,為了方便用戶交互,而不是因技術而技術的。

三、AJAX的MVC架構設計

很多人認為在成熟的框架中應用AJAX會破壞框架的完整性,比較常見的說法有三層架構的WEB應用中破壞MVC模式,其實不然。MVC的理論我就不多說了,經典的那三個層、五條線大家都很熟悉,在WEB應用中,因為瀏覽器/服務器固有的這種請求/響應的斷開式網絡通訊模式,決定了在Model層無法實現主動向View層發出數據更新事件,所以一般常見的成熟MVC框架中都將經典MVC理論稍作修改:由Model層處理完業務后通知Control層,然后由Control層承擔向View發送數據更新的義務。但是AJAX天生具有監聽功能,AJAX實現異步響應的那個OnReadyStateChange事件就具有在客戶端程序中才會有的事件監聽功能?,F在想來,利用AJAX實現的MVC模型有如下圖這樣:



理想化的設計如下所示:

  • 三層對應的文件對象:view.jsp(視圖)、action.do(控制器)、model.java(模型)
  • view.jsp是用戶看到的界面,并通過內置的AJAX對象異步方式給action.do發送請求,AJAX.OnReadyStateChange開始監聽
  • action.do接收到view.jsp發過來的請求(GET或者POST方式),通過Request判斷后發送給相應的業務/數據模型model.java
  • model.java開始執行業務操作,執行完畢直接給view.jsp頁面發送數據更新的通知,這個通知的消息有可能是XML封裝的數據,也有可能是一段文本,甚至是一段HTML代碼,當然,既然用MVC,不推薦有Model發送HTML,推薦還是用XML封裝業務數據即可。
  • view.jsp頁面中AJAX對象的OnReadyStateChange接收到了數據更新通知,根據實際情況用DOM進行頁面呈現更新。
通過以上幾步一氣呵成,一個典型的基于MVC的三層交互就完成了。當然,熟悉WEB下的MVC框架的用戶,如熟悉Struts的Java開發人員可能不習慣由Model層給View直接發送數據更新通知,那咱們也可以轉變一下,Model層業務處理完畢將更新通知先發送給Control,由Control去通知View亦可。


kelven 2006-04-04 16:06 發表評論
]]>
主站蜘蛛池模板: 延寿县| 永昌县| 罗平县| 兰州市| 博爱县| 遂川县| 成都市| 乐陵市| 清水县| 安丘市| 阿坝| 龙岩市| 玉林市| 五寨县| 孟津县| 云南省| 东乌| 文安县| 香河县| 于田县| 文山县| 卓资县| 弥渡县| 遂昌县| 启东市| 丁青县| 凭祥市| 南涧| 象州县| 同江市| 英超| 怀化市| 汉阴县| 仙居县| 西昌市| 松阳县| 安庆市| 韶山市| 自治县| 云林县| 宁河县|