Dedian  
          -- 關(guān)注搜索引擎的開發(fā)
          日歷
          <2006年10月>
          24252627282930
          1234567
          891011121314
          15161718192021
          22232425262728
          2930311234
          統(tǒng)計
          • 隨筆 - 82
          • 文章 - 2
          • 評論 - 228
          • 引用 - 0

          導(dǎo)航

          常用鏈接

          留言簿(8)

          隨筆分類(45)

          隨筆檔案(82)

          文章檔案(2)

          Java Spaces

          搜索

          •  

          積分與排名

          • 積分 - 66090
          • 排名 - 813

          最新評論

          閱讀排行榜

          評論排行榜

           

          ---祝大家中秋愉快---

          Ajax (AsynchronousJavaScript and XML)是近年來流行的一門web 技術(shù)。在Blogjava上看到有人開始在介紹AJAX,但仿佛流于概念或理論的東西,對于想用Ajax的初學(xué)者似乎不是很make sense。我想,學(xué)習(xí)任何一樣新的技術(shù),例子和步驟是極為make sense的兩樣?xùn)|西。

          筆者想結(jié)合過去的學(xué)習(xí)經(jīng)驗簡單講講使用Ajax的基本步驟和舉幾個實用例子。由于筆者主要在于后臺端的開發(fā),所以很多腳本并不是很擅長。Ajax也主要限于以前大學(xué)的修課和近期的一些為后臺端程序的測試的簡單實現(xiàn)。所以只是一個拋磚引玉的使用Ajax版本,歡迎相互學(xué)習(xí)交流。

          0. 導(dǎo)讀

          ??? 1。使用Ajax的基本流程
          ???
          2。使用Ajax的基本步驟。(簡單例子--> Demo)
          ??? 3。
          再來一個例子(Google Suggest)。(Demo)
          ??? 4。家庭作業(yè) :)


          1。使用Ajax的基本流程

          在筆者看來,Ajax更像是一個簡單的網(wǎng)絡(luò)框架,它描述著如何高效地使網(wǎng)絡(luò)前端的數(shù)據(jù)展現(xiàn)和網(wǎng)絡(luò)后端的數(shù)據(jù)之間的交互。基本上,就是瀏覽器提供一個XMLHttpRequest(當(dāng)然在IE里是ActiveXObject)的對象向后臺端的腳本程序或者Servlet Classes發(fā)送http請求,從后臺端的回應(yīng)中獲取文本數(shù)據(jù)(如xml格式和最近有人討論的Json格式)并嵌入前臺段的網(wǎng)頁中或腳本中。

          下圖是一個簡單的流程圖:



          2。使用Ajax的基本步驟。

          下面,我們結(jié)合上面的流程,以及一個簡單的例子(見這篇文章)過一遍基本的步驟。(藍色代碼為標(biāo)準寫法)

          第一步:Form 代碼:接受前臺端的輸入,并通過Action方法(方法函數(shù)里包含創(chuàng)建XMLHttpRequest對象)把request post到后臺端。

          <input id="username" name="username" type="text"
          ? onblur="checkName(this.value,'')" />
          <span class="hidden" id="nameCheckFailed">
          ? This name is in use, please try another.
          </span>

          <script language="javascript">
          function checkName(input, response)
          {
          ? if (response != ''){
          ??? // Response mode
          ??? message?? = document.getElementById('nameCheckFailed');
          ??? if (response == '1'){
          ????? message.className = 'error';
          ??? }else{
          ????? message.className = 'hidden';
          ??? }
          ? }else{
          ??? // Input mode
          ??? url? = 'http://localhost/xml/checkUserName.php?q=' + input;
          ??? loadXMLDoc(url);
          ? }
          }

          var req;

          function loadXMLDoc(url)
          {
          ??? // branch for native XMLHttpRequest object
          ??? if (window.XMLHttpRequest) {
          ??????? req = new XMLHttpRequest();
          ??????? req.onreadystatechange = processReqChange;
          ??????? req.open("GET", url, true);
          ??????? req.send(null);
          ??? // branch for IE/Windows ActiveX version
          ??? } else if (window.ActiveXObject) {
          ??????? req = new ActiveXObject("Microsoft.XMLHTTP");
          ??????? if (req) {
          ??????????? req.onreadystatechange = processReqChange;
          ??????????? req.open("GET", url, true);
          ??????????? req.send();
          ??????? }
          ??? }
          }
          </script>


          注:
          1。 這里的form只是一個input box,action的方法是onblur,就是響應(yīng)失去焦點的事件,然后調(diào)用一個函數(shù)checkName, 這個函數(shù)里通過XMLHttpRequest向PHP server script 發(fā)送Post請求(看得出來,這里的php server script的文件名叫checkUserName.php,唯一參數(shù)是q)。
          2。函數(shù)loadXMLDoc里有個通用的創(chuàng)建XMLHttpRequest對象的代碼,標(biāo)準代碼整理如下:
          ??????? var req;
          ??? ??? function foo()
          ??? ??? {
          ??? ??? ??? req = false;

          ??? ??? ??? // branch for native XMLHttpRequest object
          ??? ??? ??? if(window.XMLHttpRequest)
          ??? ??? ??? {
          ??? ??? ??? ??? try
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? req = new XMLHttpRequest();
          ??? ??? ??? ??? }
          ??? ??? ??? ??? catch(e)
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? req = false;
          ??? ??? ??? ??? }
          ??? ??? ??? }
          ??? ??? ??? else if(window.ActiveXObject) // branch for IE/Windows ActiveX version
          ??? ??? ??? {
          ??? ??? ??? ??? try
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? req = new ActiveXObject("Msxml2.XMLHTTP");
          ??? ??? ??? ??? }
          ??? ??? ??? ??? catch(e)
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? try
          ??? ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? ??? req = new ActiveXObject("Microsoft.XMLHTTP");
          ??? ??? ??? ??? ??? }
          ??? ??? ??? ??? ??? catch(e)
          ??? ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? ??? req = false;
          ??? ??? ??? ??? ??? }
          ??? ??? ??? ??? }
          ??? ??? ??? }
          ??? ??? ??? if(req)
          ??? ??? ??? {
          ??? ?? ?? ?? ?? ??
          //do something here
          ???? ??? ??? }
          ??? ??? ???

          ??? ??? }

          第二步:響應(yīng)文本處理代碼:XMLHttpRequest對象里有個類似消息響應(yīng)函數(shù)的屬性,即通過設(shè)置 req.onreadystatechange 來告訴XMLHttpRequest在哪個函數(shù)里處理服務(wù)端返回的文本信息。
          如在上面的例子中:
          req.onreadystatechange = processReqChange;
          那么我們接著要有一個processReqChange的函數(shù):
          function processReqChange() 
          {
          // only if req shows "complete"
          if (req.readyState == 4) {
          // only if "OK"
          if (req.status == 200)
          {
          // ...processing statements go here...
          processResponse();
          } else {
          alert("There was a problem retrieving
          the XML data:\n" + req.statusText);
          }
          }
          }


          function processResponse()
          {
          response = req.responseXML.documentElement;
          method = response.getElementsByTagName('method')[0].firstChild.data;
          result = response.getElementsByTagName('result')[0].firstChild.data;
          eval(method + '(\'\', result)');

          }
          注:
          1。 基本上processReqChange 函數(shù)是標(biāo)準代碼的寫法。
          2。這里要用到前面定義的全局變量(XMLHttpRequest對象)req

          第三步:后臺端代碼(這個例子是php server script):接受前臺端的請求,處理其參數(shù),并返回相應(yīng)的結(jié)果。

          文件名: checkUserName.php

          <?php
          header('Content-Type: text/xml');

          function nameInUse($q)
          {?
          ? if (isset($q)){
          ??? switch(strtolower($q))
          ??? {
          ????? case? 'drew' :
          ????????? return '1';
          ????????? break;
          ????? case? 'fred' :
          ????????? return '1';
          ????????? break;
          ????? default:
          ????????? return '0';
          ??? }
          ? }else{
          ??? return '0';
          ? }
          ?
          }
          ?>
          <?php echo '<?xml version="1.0" encoding="UTF-8"? standalone="yes"?>'; ?>
          <response>
          ? <method>checkName</method>
          ? <result><?php
          ??? echo nameInUse($_GET['q']) ?>
          ? </result>
          </response>
          注:代碼很簡單,就不用解釋了。這里返回的是xml格式的字符串。

          總體效果見這里
          輸入"fred"或者"drew"的名字,失去焦點后會顯示名字已存在的信息。


          ?3。再來一個例子。

          這里再講一個實用的例子,這是以前上課的一個課堂作業(yè),也很有代表性。是關(guān)于Google Suggest(好像新的Google Toolbar上就用的這個功能)的應(yīng)用問題。這里是寫好的DEMO。現(xiàn)在越來越多的網(wǎng)站提供類似Web Service的API, 我們利用他們提供的API URL可以返回一些我們用的著的數(shù)據(jù),放在我們的網(wǎng)頁上。這里就用的上Ajax。只不過有些返回來的文本數(shù)據(jù)是xml格式的,就可以利用上面的簡單例子來處理,但很多像Google Suggest那樣是返回一段類似代碼格式的文本。我們就要利用Javascript的eval函數(shù),把這些文本當(dāng)作一段代碼在嵌入自己的網(wǎng)頁中。如果嵌入的代碼中含有函數(shù),則需要自己再寫一個同名的函數(shù)作為實現(xiàn)。(這就是流程圖中的optional的func 3)

          這里完整代碼就不貼了,貼一些關(guān)鍵代碼(原本后臺端是用Java Servlet寫的,但做demo的空間沒有Tomcat不支持Servlet,所以改用Php實現(xiàn),大家可以自己用Java再寫一邊作為家庭作業(yè) :) ):

          1) form 代碼:

          <form name = "QForm" method="POST" action="google_suggest.php">
          ??? <table bgcolor="8080C0" width="90%" >
          ??? <tr>
          ??? ??? <td? nowrap>Search Term:</td>
          ??? ??? <td ><input type="text" name="qtext"? onkeyup="return GetSuggestion()" size="60"></td>
          ??? </tr>
          ??? <tr>
          ??? ??? <th colspan="2" align="left" bgcolor="#A8A8FF"><DIV id=google_suggest_target>results go here . . . </DIV></th>
          ??? </tr>
          ??? </table>
          ??? </form>

          注:
          a. 看得出來,要把查詢的字符串post到google_suggest.php上
          b. action的函數(shù)是GetSuggestion(),其返回的字符串會顯示在預(yù)留的網(wǎng)頁空間里。

          2) 后臺端代碼(PHP):這里主要接收前臺的請求,并不請求轉(zhuǎn)化為向Google Suggest的API URL請求,把接收到的文本信息返回給前端。代碼很簡單,如下:

          文件名:google_suggest.php

          <?php
          function getGoogleSuggest($q)
          {

          ??? $url = "http://www.google.com/complete/search?hl=en&js=true&qu=" . $q;
          ??? return file_get_contents($url);
          }
          ?>

          <?php echo getGoogleSuggest($_POST['q']) ?>

          注:
          a。 Google Suggest API 返回的是一個代碼格式的文本信息,如下:
          sendRPCDone(frameElement, "", new Array(), new Array(), new Array(""));
          所以我們再前臺接受到這個文本信息之后,應(yīng)該寫一個sendRPCDone的函數(shù)來做進一步信息處理(比如說列表出查詢結(jié)果)。

          3) 前臺文本處理代碼:

          ??? <script type="text/javascript">
          ??? ??? var req;
          ??? ??? function GetSuggestion()
          ??? ??? {
          ??? ??? ??? req = false;
          ??? ??? ??? var f = document.QForm;

          ??? ??? ??? // branch for native XMLHttpRequest object
          ??? ??? ??? if(window.XMLHttpRequest)
          ??? ??? ??? {
          ??? ??? ??? ??? try
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? req = new XMLHttpRequest();
          ??? ??? ??? ??? }
          ??? ??? ??? ??? catch(e)
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? req = false;
          ??? ??? ??? ??? }
          ??? ??? ??? }
          ??? ??? ??? else if(window.ActiveXObject) // branch for IE/Windows ActiveX version
          ??? ??? ??? {
          ??? ??? ??? ??? try
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? req = new ActiveXObject("Msxml2.XMLHTTP");
          ??? ??? ??? ??? }
          ??? ??? ??? ??? catch(e)
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? try
          ??? ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? ??? req = new ActiveXObject("Microsoft.XMLHTTP");
          ??? ??? ??? ??? ??? }
          ??? ??? ??? ??? ??? catch(e)
          ??? ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? ??? req = false;
          ??? ??? ??? ??? ??? }
          ??? ??? ??? ??? }
          ??? ??? ??? }
          ??? ??? ??? if(req)
          ??? ??? ??? {
          ??? ??? ??? ??? var url = "google_suggest.php";
          ???????
          ??? ??? ??? ??? req.onreadystatechange = processReqChange;
          ??? ??? ??? ??? req.open("POST", url, true);

          ??????? ??? ??? req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
          ??? ??? ??? ??? req.setRequestHeader("Method", "POST " + url + " HTTP/1.1");
          ??? ??? ??? ??? req.send("q=" + escape(document.QForm.qtext.value));
          ??? ??? ??? }
          ??? ??? ???

          ??? ??? }
          ??? ???
          ??? ??? function processReqChange()
          ??? ??? {
          ??? ??? ??? if(req.readyState == 4) // only if req shows "loaded"
          ??? ??? ??? {
          ??? ??? ???????????????? if (req.status == 200) // only if "OK"
          ??? ??? ???????????????? {
          ??? ??? ???????????????? ??? ??? x = req.responseText;
          ??? ??? ???????????????????????? eval(x);
          ??
          ? ??? ???????????????? }
          ??? ??? ???????????????? else
          ??? ??? ???????????????? {
          ??? ??? ?????????? ??? ??? ????? alert("There was a problem retrieving the XML data:\n" + req.statusText);
          ??? ??? ???????????????? }
          ??? ??? ??? }
          ??? ??? ??? else if(req.readyState == 2)
          ??? ??? ??? {
          ??? ??? ??? }
          ??? ??? }
          ??? ???
          ??? ??? function sendRPCDone(frameElement, qString, arr1, arr2, arr3)
          ??? ??? {
          ??? ???
          ??? ??? ??? var suggest_results = eval(arr1);
          ??? ??? ??? var counts = eval(arr2);
          ??? ??? ??? var htmlstr = "<TABLE cellspacing=4 border=0>";
          ??? ??? ??? for (var i=0; i < suggest_results.length; i++)
          ??? ??? ??? {
          ??? ??? ??? ??? htmlstr += "<tr><td><a href=\"javascript:self.location=\'http://www.google.com/search?hl=en&q=" + suggest_results[i] + "&btnG=Google+Search\'\">" + suggest_results[i] + "</a></td>";
          ??? ??? ??? ??? htmlstr += "<TD width=200><font color= 228b22>" + counts[i] + "</font></TD></TR>"
          ??? ??? ?????? ??? ?
          ??? ??? ??? }
          ??? ??? ??? htmlstr += "</TABLE>";
          ??? ??? ??? document.getElementById("google_suggest_target").innerHTML = htmlstr;
          ??? ???
          ??? ??? }
          ??? ???
          ??? ??? </script>

          4。家庭作業(yè) :)

          一定要自己寫一些代碼,才能鞏固知識:)
          題目:
          我們經(jīng)常用del.icio.us來收藏我們喜歡的網(wǎng)站或者文章,并加一些類似讀書筆記的注釋。那么我們怎么利用del.icio.us提供的API來訪問我們的讀書筆記信息,并顯示在自己的Blog里呢?
          提示:
          1。你要有一個del.icio.us的賬號,并且已經(jīng)有所網(wǎng)頁收藏作為實驗數(shù)據(jù):)
          2。API URL 是 "http://del.icio.us/feeds/json/" + "你的賬號名";自己參看一下,看返回什么樣的格式文本。另外,如果要限制返回的記錄數(shù),可以加"?count=10"這樣的參數(shù)。


          最后,祝大家中秋愉快!

          ---------------------------完----------------------------




          posted on 2006-10-07 07:05 Dedian 閱讀(2254) 評論(2)  編輯  收藏 所屬分類: Java Memo
          評論:
          • # re: Ajax 淺談  壞男孩 Posted @ 2006-10-07 12:57
            佩服樓主十月一期間仍然寫博啊!  回復(fù)  更多評論   

          • # re: Ajax 淺談  123bingbing Posted @ 2006-10-11 10:24
            如果你是深藏不露的編程高手,www.mylinux.com不僅讓你有一展身手的好機會,更能贏得一份額外收入!
              回復(fù)  更多評論   

           
          Copyright © Dedian Powered by: 博客園 模板提供:滬江博客
          主站蜘蛛池模板: 讷河市| 临桂县| 尼玛县| 临沭县| 宜城市| 黄浦区| 平乡县| 犍为县| 利川市| 宁陕县| 徐州市| 泸定县| 峨边| 栖霞市| 壤塘县| 丰城市| 贺州市| 阿克陶县| 肥城市| 广安市| 吴堡县| 贵阳市| 福贡县| 镇雄县| 会同县| 于都县| 连平县| 汝南县| 宁都县| 昌平区| 油尖旺区| 平塘县| 如皋市| 乐亭县| 弥勒县| 昌平区| 南宫市| 平远县| 凯里市| 谢通门县| 仙居县|