国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
用XMLHttpRequest和struts實(shí)現(xiàn)AJAX(轉(zhuǎn))

http://blog.dreambrook.com/zlliu/archive/2005/05/18/623.aspx
大約五年前我曾參與一個(gè)web應(yīng)用的開發(fā),該應(yīng)用的一個(gè)主要需求是要提供類似window胖客戶端的外觀和操作方式。先不討論為什么當(dāng)初這個(gè)項(xiàng)目不直接使用window胖客戶端,而把這個(gè)難題帶到了web開發(fā)中,事實(shí)是在五年前還沒有多少這樣的東西(基于web的胖客戶端)存在。

作為對這一課題研究的結(jié)果,我偶然發(fā)現(xiàn)了一些用于實(shí)現(xiàn)上述需求的非典型技術(shù)和方法。使用這些技術(shù)實(shí)現(xiàn)的web應(yīng)用,直到現(xiàn)在很多人還不能相信它們是基于web的,然后事實(shí)上你確實(shí)是通過瀏覽器來訪問它們。

讓我沒想到的是,幾年后的今天我所實(shí)現(xiàn)的那種東西又出現(xiàn)另一種實(shí)現(xiàn)方式,它就是AJAX。AJAX是Adaptive Path的人們發(fā)明的一個(gè)名詞,全稱是Asynchronous Javascript + XML。

這說明了一件事情,提煉你曾經(jīng)擁有的好主意是致富的一個(gè)好方法。如果當(dāng)初我意識到我所作的是一件很特別的東西......我跑題了

Google正在使用這項(xiàng)技術(shù),許多其它的組織也是。但它究竟是個(gè)什么東西呢?概括地說,AJAX不是一項(xiàng)技術(shù),只是一種考慮問題的方法,這個(gè)方法整合了多種技術(shù)且基于這樣一種考慮:為每一個(gè)客戶請求構(gòu)造一張全新的web頁面是低效的且應(yīng)該避免的。

舉個(gè)例子,假設(shè)你再一張web頁面上放了兩個(gè)SELECT元素,你想讓第二個(gè)SELECT元素的內(nèi)容隨著第一個(gè)的內(nèi)容變化而變化,這是實(shí)際開發(fā)中很常見的一個(gè)問題而且有多種解決方案。

AJAX對此問題的解決方法是:只重畫頁面的一小部分,在這里是第二個(gè)SELECT。

AJAX基于一種稱為XMLHttpRequest的組件。討厭Microsoft的人要開始叫嚷了,因?yàn)檫@是Microsoft的東西。不錯(cuò),Microsoft有些東西做得挺好,而且先于其他人做了。Microsoft最初實(shí)現(xiàn)XMLHttpRequest是在Windows下的IE 5中,其實(shí)現(xiàn)方式是ActiveX對象(好吧,他們做得不完全對?。?。Monilla項(xiàng)目在Mozilla 1.0中實(shí)現(xiàn)了一個(gè)本地版本,還有Netscape 7。其他的還有Apple的Safari 1.2,Opera 7.60,F(xiàn)irefox等,有提供了類似的功能。

好,讓我們切開這塊蛋糕看看它的實(shí)現(xiàn)。

 XMLHttpRequest是一個(gè)客戶端組件,需要在Javascript腳本中實(shí)例化后才能使用。幸運(yùn)的事,這樣做非常簡單。在IE中,實(shí)現(xiàn)代碼如下:

 var req = new ActiveXObject("Microsoft.XMLHTTP");

對其他的瀏覽器,使用:

var req = new XMLHttpRequest();

你當(dāng)然想在代碼中實(shí)現(xiàn)一些判斷邏輯,有很多方法可以做到這點(diǎn),但是我傾向于簡單的方案,比如只是檢查一下某個(gè)對象是否存在:

var req;

if (window.XMLHttpRequest) { // Non-IE browsers  

req = new XMLHttpRequest();

} else if (window.ActiveXObject) { // IE  

req = new ActiveXObject("Microsoft.XMLHTTP");

}

不管你怎么實(shí)現(xiàn),上面的代碼執(zhí)行之后,你會發(fā)現(xiàn)變量req現(xiàn)在指向了一個(gè)XMLHttpRequest對象,這個(gè)對象有一組屬性和方法,列舉如下:

Property                                  Description

onreadystatechange                  Event handler for an event that fires at every state change

readyState                                Status:

0 = uninitialized

1 = loading

2 = loaded

3 = interactive

4 = complete

responseText                            Data returned from server in string form

responseXML                          DOM-compatible document object of data returned

status                                        HTTP status code (i.e., 200, 404, 500, etc.)

statusText                                 String message associated with the status code

 

Method                                   Description

abort()                                      Stops the current request

getAllResponseHeaders()         Returns all headers (name and value) as a string

getResponseHeader(                Returns the value of the specified header

"<headerName>")

open("", "URL"[,       Opens a connection and retrieves response from the specified URL.

asyncFlag[, ""[,      Can also specify optional values method (GET/POST), username and

"<password>"]]])                     password for secured sites

 send(content)                           Transmits request (can include postable string or DOM object data)

setRequestHeader                    Assigns values to the specifed header

("<name>", "")

 

繼續(xù)介紹之前,我強(qiáng)烈建議你運(yùn)行本文末尾給出的那個(gè)web應(yīng)用。如果你還沒有下載示例應(yīng)用,請參見本文末尾給出的鏈接,下載并安裝到你的servlet引擎中。示例應(yīng)用是以展開目錄的結(jié)構(gòu)形式發(fā)布的,所以只要解壓后拷貝解壓出的目錄就可以工作。比如,如果你使用Tomcat,只要把xhrstruts目錄拷貝到\webapps下就可以了。完成之后,啟動服務(wù)器即可。

該應(yīng)用可以通過http://localhost:8080/xhrstruts (將8080換成你的服務(wù)器所監(jiān)聽的端口)來訪問。  它展示了幾種不同的應(yīng)用場景:一個(gè)可排序的table,一個(gè)可以改變另一個(gè)下拉框內(nèi)容的下拉框(如上文所述),一個(gè)RSS feed 解析器。正像本文標(biāo)題中說明的那樣,該示例基于struts。盡管AJAX可以完全獨(dú)立于struts和任何其他的后端技術(shù),但我使用Java,而且使用struts,所以......

web應(yīng)用中的所有例子都在代碼頭部的標(biāo)簽中包含有一段代碼,盡管每個(gè)都有所不同,總體是出自相同的基礎(chǔ)代碼,如下:

var req;

  var which;

 

  function retrieveURL(url) {

    if (window.XMLHttpRequest) { // Non-IE browsers

      req = new XMLHttpRequest();

      req.onreadystatechange = processStateChange;

      try {

        req.open("GET", url, true);

      } catch (e) {

        alert(e);

      }

      req.send(null);

    } else if (window.ActiveXObject) { // IE

      req = new ActiveXObject("Microsoft.XMLHTTP");

      if (req) {

        req.onreadystatechange = processStateChange;

        req.open("GET", url, true);

        req.send();

      }

    }

  }

 

  function processStateChange() {

    if (req.readyState == 4) { // Complete

      if (req.status == 200) { // OK response

        document.getElementById("urlContent").innerHTML = req.responseText;

      } else {

        alert("Problem: " + req.statusText);

      }

    }

  }
 

這段代碼邏輯很簡單。你可以調(diào)用retieveURL()方法,傳入你想訪問的URL,該方法根據(jù)瀏覽器類型實(shí)例化相應(yīng)的XMLHttpRequest對象,開啟一個(gè)對指定URL的請求。請留意這里的try...catch語句塊,加入這段代碼是因?yàn)橛行g覽器(比如Firefox)不允許使用XMLHttpRequest從一個(gè)域到另一個(gè)域發(fā)送請求,換句話說,如果你從www.omnytex.com/test.htm頁面請求www.cnn.com,該類瀏覽器是不允許的,但是,訪問www.omnytext.com/whatever.htm是可以的。IE允許這種跨域訪問但是需要用戶驗(yàn)證。

有一行代碼很重要:req.onreadystatechange = processStateChange,這行代碼設(shè)定了一個(gè)事件處理器。當(dāng)request的狀態(tài)發(fā)生變化時(shí),processStateChange()方法將被調(diào)用。然后,你可以檢查XMLHttpRequest對象的狀態(tài)進(jìn)行后續(xù)處理。上面的列表中列出了所有可能的值。這里我們關(guān)心的是請求完成之后,下面要做的事就是檢查收到的HTTP響應(yīng)代碼,除200(HTTP OK)外的任何代碼都預(yù)示著需要顯示錯(cuò)誤信息。

在這個(gè)例子中,如果響應(yīng)接收完成且沒有異常,我們就把接收到的代碼插入urlContent span,然后最終效果就顯示在頁面上。

語法上講,這就是所有XMLHttpRequest的使用方法!

另一個(gè)更有趣的例子是web應(yīng)用中的第二個(gè),動態(tài)排序table。下面是完整的頁面代碼:

<code>

<html>

<head>

<title>Example 2</title>

 

<script>

 

  var req;

  var which;

 

  function retrieveURL(url) {

    if (window.XMLHttpRequest) { // Non-IE browsers

      req = new XMLHttpRequest();

      req.onreadystatechange = processStateChange;

      try {

        req.open("GET", url, true);

      } catch (e) {

        alert(e);

      }

      req.send(null);

    } else if (window.ActiveXObject) { // IE

      req = new ActiveXObject("Microsoft.XMLHTTP");

      if (req) {

        req.onreadystatechange = processStateChange;

        req.open("GET", url, true);

        req.send();

      }

    }

  }

 

  function processStateChange() {

    if (req.readyState == 4) { // Complete

      if (req.status == 200) { // OK response

        document.getElementById("theTable").innerHTML = req.responseText;

      } else {

        alert("Problem: " + req.statusText);

      }

    }

  }

 

</script>

 

</head>

<body onLoad="retrieveURL(‘example2RenderTable.do‘);">

 

<h1>Example 2</h1>

Dynamic table.<hr>

<p align="right"><a href="home.do">Return home</a></p><br>

This example shows how a table can be built and displayed on-the-fly by showing

sorting of a table based on clicks on the table headers.

<br><br>

 

<span id="theTable"></span>

<br>

 

</body>

</html>

</code>
 

請注意中幾乎相同的代碼。這里我們實(shí)際請求的是一個(gè)Struts的Action,該action返回繪制table的HTML腳本。還有其他方法可以達(dá)到相同的效果而無需在Action中產(chǎn)生HTML,但這是最快捷而且工作良好的。當(dāng)頁面最初載入的時(shí)候我們發(fā)送請求到Action得到一個(gè)最初的table,點(diǎn)擊任何列標(biāo)題可以將該table排序并重新繪制。

我們再來看另外一個(gè)例子,RSS feed 解析器:

<code>

<html>

<head>

<title>Example 6</title>

</head>

 

<script>

 

  var req;

  var which;

 

  function retrieveURL(url) {

    if (url != "") {

      if (window.XMLHttpRequest) { // Non-IE browsers

        req = new XMLHttpRequest();

        req.onreadystatechange = processStateChange;

        try {

          req.open("GET", url, true);

        } catch (e) {

          alert(e);

        }

        req.send(null);

      } else if (window.ActiveXObject) { // IE

        req = new ActiveXObject("Microsoft.XMLHTTP");

        if (req) {

          req.onreadystatechange = processStateChange;

          req.open("GET", url, true);

          req.send();

        }

      }

    }

  }

 

  function processStateChange() {

    if (req.readyState == 4) { // Complete

      if (req.status == 200) { // OK response

        // We‘re going to get a list of all tags in the returned XML with the

        // names title, link and description.  Everything else is ignored.

        // For each that we find, we‘ll constuct a simple bit of HTML for

        // it and build up the HTML to display.  When we hit a title,

        // link or description element that isn‘t there, we‘re done.

        xml = req.responseXML;

        i = 0;

        html = "";

        while (i >= 0) {

          t = xml.getElementsByTagName("title")[i];

          l = xml.getElementsByTagName("link")[i];

          d = xml.getElementsByTagName("description")[i];

          if (t != null && l != null && d != null) {

            t = t.firstChild.data;

            l = l.firstChild.data;

            d = d.firstChild.data;

            html += "<a href=\"" + l + "\">" + t + "</a><br>" + d + "<br><br>";

            i++;

          } else {

            i = -1;

          }

        }

        document.getElementById("rssData").innerHTML = html;

      } else {

        alert("Problem: " + req.statusText);

      }

    }

  }

 

</script>

 

<body>

 

<h1>Example 6</h1>

RSS example.<hr>

<p align="right"><a href="home.do">Return home</a></p><br>

This example is a more real-world example.  It retrieves an RSS feed from one

of three user-selected sources, parses the feed and displays the headlines

in clickable form.  This demonstrates retrieving XML from a server and

dealing with it on the client.

<br><br>

<b>Note that the RSS feed XML is actually stored as files within this

webapp.  That is because some browsers will not allow you to retrieve

content with XMLHttpRequest outside the domain of the document trying to

do the call.  Some browsers will allow it with a warning though.</b>

<br><br>

<form name="rssForm">

  <select name="rssFeed" onChange="retrieveURL(this.value);">

    <option value=""></option>

    <option value="cnn_rss.xml">CNN Top Stories</option>

    <option value="slashdot_rss.xml">Slashdot</option>

    <option value="dans_rss.xml">Dan‘s Data</option>

  </select>

</form>

<hr><br>

<span id="rssData"></span>

<br>

 

</body>

</html>

</code>
 

首先要注意的是RSS feed XML文件實(shí)際上是包含在web應(yīng)用中的本地文件。一個(gè)真正實(shí)用使用XMLHttpRequest的RSS閱讀器是不可能實(shí)現(xiàn)的因?yàn)橐婕暗娇缬蛱幚?。然而,一個(gè)可行的方法是寫一個(gè)Action從真正的URL處得到feed然后將之返回給請求頁面,參見示例7。除了需要一個(gè)Action作為代理來得到RSS feed外,頁面上代碼還是相同的。

上面的例子跟其它的類似,除了在事件處理器中的XML解析代碼。這只是一個(gè)簡化的例子,我們只是簡單地忽略了除標(biāo)題之外的其他標(biāo)簽。在一個(gè)真實(shí)的例子中(比如一個(gè)請求復(fù)雜XML的應(yīng)用),解析代碼會變得復(fù)雜,但這個(gè)我留給讀者作為練習(xí)。

讓我們以一個(gè)在請求中提交數(shù)據(jù)的例子做結(jié),中的腳本如下:

var req;

  var which;

 

  function submitData() {

    // Construct a CSV string from the entries.  Make sure all fields are

    // filled in first.

    f = document.theForm.firstName.value;

    m = document.theForm.middleName.value;

    l = document.theForm.lastName.value;

    a = document.theForm.age.value;

    if (f == "" || m == "" || l == "" || a == "") {

      alert("Please fill in all fields first");

      return false;

    }

    csv = f + "," + m + "," + l + "," + a;

    // Ok, so now we retrieve the response as in all the other examples,

    // except that now we append the CSV onto the URL as a query string,

    // being sure to escape it first.

    retrieveURL("example5Submit.do?csv=" + escape(csv));

  }

 

  function retrieveURL(url) {

    if (window.XMLHttpRequest) { // Non-IE browsers

      req = new XMLHttpRequest();

      req.onreadystatechange = processStateChange;

      try {

        req.open("GET", url, true);

      } catch (e) {

        alert(e);

      }

      req.send(null);

    } else if (window.ActiveXObject) { // IE

      req = new ActiveXObject("Microsoft.XMLHTTP");

      if (req) {

        req.onreadystatechange = processStateChange;

        req.open("GET", url, true);

        req.send();

      }

    }

  }

 

  function processStateChange() {

    if (req.readyState == 4) { // Complete

      if (req.status == 200) { // OK response

        document.getElementById("theResponse").innerHTML = req.responseText;

      } else {

        alert("Problem: " + req.statusText);

      }

    }

  }
 

在這個(gè)例子中,我們只是簡單地用用戶的輸入創(chuàng)建了一個(gè)以逗號分割的字符串。你當(dāng)然可以創(chuàng)建一個(gè)XML文檔然后提交,事實(shí)上那是更常見的情況。但是這正是我不想那樣做的一部分原因:我想告訴讀者你并不一定非要使用XMLHttpRequest對象來傳輸XML。就本例而言,除了將一個(gè)CSV字符串添加到URL之外并沒有做任何事情。在網(wǎng)上有不計(jì)其數(shù)的例子演示了如何創(chuàng)建XML文檔并使用XMLHttpRequest.send()方法提交,我強(qiáng)烈推薦你閱讀相關(guān)文檔,當(dāng)然,如果你使用這種方法的話。

我希望這篇簡短的文章和附加的例子可以給你一個(gè)好的研究XMLHttpRequest對象的起點(diǎn)。在結(jié)束之前我還想說AJAX概念本身并不強(qiáng)制你使用XMLHttpRequest對象,你可以使用其他方法得到相同的效果,比如代替XMLHttpRequest的隱藏frame,這正是我在本文開頭提到的在五年前的那個(gè)項(xiàng)目中采用的方法。然而,XMLHttpRequest的確使得AJAX概念更容易實(shí)現(xiàn),而且更標(biāo)準(zhǔn)。請參見Google研究這種技術(shù)的強(qiáng)大之處。

但是,我提醒所有認(rèn)為全部的web應(yīng)用都應(yīng)該用這種方法開發(fā)的人,我不認(rèn)為這是web開發(fā)的不二法門。在某些情況下它是一個(gè)好的方案,但在其他情況下不是。如果獲得盡可能多的瀏覽者是你的目標(biāo),你最好放棄這種方案。如果一個(gè)用戶取消了瀏覽器的腳本解釋功能(而你的網(wǎng)站除了這又沒有其他出彩的地方),這就不是一個(gè)好的情況。還有其他AJAX不適用之處,但是你完全可以把它當(dāng)成你工具箱中的一個(gè)普通工具:它適合某些工作,不適合其他工作。畢竟,你不能指望用一個(gè)膠水槍釘釘子吧?

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
java.net: Sprinkle Some AJAX Magic in Your Struts Web Application part II
看看如何在Struts應(yīng)用中施展AJAX魔法-JSP
AJAX應(yīng)用在JavaRSS.com
使用AJAX技術(shù)構(gòu)建更優(yōu)秀的Web應(yīng)用程序
Ajax的經(jīng)典示例
Ajax簡單實(shí)例
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服