• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    Ajax鋪設了更好的開發Web應用的道路

    發布: 2007-6-06 16:53 | 作者: 網絡轉載 | 來源: 網絡 | 查看: 28次 | 進入軟件測試論壇討論

    領測軟件測試網

    頁面重載提出了一個在Web應用開發中最大的可用性障礙,對于Java開發來說也是一個重大的挑戰。在本文中,作者Philip McCarthy介紹了通過后臺通道的方法來創建動態Web應用的經驗。

    Ajax(Asynchronous JavaScript and XML)是一個結合了Java技術、XML、以及JavaScript的編程技術,可以讓你構建基于Java技術的Web應用,并打破了使用頁面重載的慣例。

    Ajax,異步JavaScript與XML,是使用客戶端腳本與Web服務器交換數據的Web應用開發方法。這樣,Web頁面不用打斷交互流程進行重新加裁,就可以動態地更新。使用Ajax,你可以創建接近本地桌面應用的,直接的、高可用的、更豐富的、更動態的Web用戶接口界面。

    Ajax不是一個技術,它更像是一個模式—標志并描述有用的設計技巧的一種方法。對于剛了解它的許多開發人員來說,它是一種新的感覺,但是實現Ajax的所有組件都已存在了許多年。

    當前的熱鬧是因為在2004與2005年出現了一些基于Ajax的非常動態的WebUI,尤其是Google的GMail與Maps應用系統、與照片共享網站Flickr。這些UI充分地使用了后臺通道,也被一些開發者稱為“Web 2.0”,并導致了大家對Ajax應用興趣的猛漲。

    在本系列中,我將給出所有你需要的開發你自己的Ajax應用的工具。在這第一篇文章中,我將解釋在Ajax背后的概念,示范為基于Web的應用系統創建一個Ajax接口的基本步驟。我將使用示例代碼來示范實現Ajax動態接口的服務器端Java代碼與客戶端JavaScript腳本。最后,我將指出一些Ajax方法中易犯的錯誤,以及在創建Ajax應用時應該考慮的廣泛范圍內的可用性與易訪問性方面的問題。

    一個更好的購物車

    你可以使用Ajax來加強傳統的Web應用,通過消除頁面載入來使交互更流暢。為了示范它,我將使用一個簡單的,能動態更新加入的物品購物車。結合一個在線商店,這個方法可以不用等待點擊后的頁面重載,而讓我們繼續瀏覽并挑選物品到購物車中。

    雖然,本文中的代碼針對購物車例子,但其中展示的技術可以用到其它的Ajax應用中。列表1中展示了購物車示例所使用的HTML代碼。在整篇文章中,我都將會引用到這些HTML代碼。

    Ajax處理過程

    一個Ajax交互從一個稱為XMLHttpRequest的JavaScript對象開始。如同名字所暗示的,它允許一個客戶端腳本來執行HTTP請求,并且將會解析一個XML格式的服務器響應。Ajax處理過程中的第一步是創建一個XMLHttpRequest實例。使用HTTP方法(GET或POST)來處理請求,并將目標URL設置到XMLHttpRequest對象上。

    現在,記住Ajax如何首先處于異步處理狀態?當你發送HTTP請求,你不希望瀏覽器掛起并等待服務器的響應,取而代之的是,你希望通過頁面繼續響應用戶的界面交互,并在服務器響應真正到達后處理它們。

    要完成它,你可以向XMLHttpRequest注冊一個回調函數,并異步地派發XMLHttpRequest請求?刂茩囫R上就被返回到瀏覽器,當服務器響應到達時,回調函數將會被調用。

    在Java Web服務器上,到達的請求與任何其它HttpServletRequest一樣。在解析請求參數后,servlet執行必需的應用邏輯,將響應序列化到XML中,并將它寫回HttpServletResponse。

    回到客戶端,注冊在XMLHttpRequest上的回調函數現在會被調用來處理由服務器返回的XML文檔。最后,通過更新用戶界面來響應服務器傳輸過來數據,使用JavaScript來操縱頁面的HTML DOM。圖1是Ajax處理過程的一個時序圖。

    圖1:Ajax處理過程

    現在,你應該對Ajax處理過程有了一個高層視圖。我將進入其中的每一步看看更細節的內容。如果你找不到自己的位置時,就回頭再看看圖1,加—因為Ajax方法的異步本質,所以時序圖并不是筆直向前的。

    發送一個XMLHttpRequest

    我將從Ajax時序圖的起點開始:從瀏覽器創建并發送一個XMLHttpRequest。不幸的是,在不同的瀏覽器中創建XMLHttpRequest的方法都不一樣。列表2中示例的JavaScript函數消除了這些與瀏覽器種類相關的問題,正確檢測與當前瀏覽器相關的方法,并返回一個可以使用的XMLHttpRequest。最好將它看成備用代碼,將它簡單拷貝到你的JavaScript庫中,在需要一個XMLHttpRequest時使用它即可。

    列表2:跨瀏覽器創建一個XMLHttpRequest

    /*
     * 返回一個新建的XMLHttpRequest對象,
     若瀏覽器不支持則失敗
    */
    function newXMLHttpRequest()
    {
      var xmlreq = false;
      if (window.XMLHttpRequest)
      {
        // 在非Microsoft瀏覽器中
     創建XMLHttpRequest對象
        xmlreq = new XMLHttpRequest();
      } else if (window.ActiveXObject)
      {
        //通過MS ActiveX創建XMLHttpRequest
        try {
          // 嘗試按新版Inte.netExplorer方法創建
          xmlreq = new ActiveXObject
       ("Msxml2.XMLHTTP");
        } catch (e1) {
          // 創建請求的ActiveX對象失敗
          try {
            // 嘗試按老版InternetExplorer方法創建
            xmlreq = new ActiveXObject
      ("Microsoft.XMLHTTP");
          } catch (e2) {
            // 不能通過ActiveX創建XMLHttpRequest
          }
        }
      }
      return xmlreq;
    }

    稍后,我將討論如何對待不支持XMLHttpReauest的瀏覽器的一些技巧,F在,列表2中展示的示例函數將總是可以返回一個XMLHttpReauest實例。

    回到購物車例子的場景中,只要用戶針對某一個目錄條目點擊了Add to Cart按鈕,我就要調用一個Ajax交互。名為addToCart()的onclick函數通過Ajax調用(如列表1中所示)來負責更新購物車的狀態。

    在列表3中,addToCart()要做的第一件事就是通過調用newXMLHttpReauest函數(如列表2中所示)來獲取一個XMLHttpRequest的實例,并且注冊一個回調函數來接受服務器響應(我將在稍后詳細解釋,請參見列表6)。

    因為,此請求將會修改服務器狀態,我將使用一個HTTP POST來處理它。通過POST傳送數據需要三個步驟:首先,我需要打開一個到進行通訊的服務器資源的POST連接—在現在例子中是一個URL映射為cart.do的服務器端servlet。

    下一步,設置XMLHttpRequest的頭信息,以標志請求的內容為form-encoded。最后,將form-encoded數據作為請求體,并發送此請求。列表3中集中展示了這些步驟。

    列表3:發送一個添加到購物車XMLHttpRequest

    /*
     * 通過產品編碼,在購物車中添加一個條目
     * itemCode – 需要添加條目的產品編碼
     */
    function addToCart(itemCode)
    {
      // 獲取一個XMLHttpRequest實例
      var req = newXMLHttpRequest();
      // 設置用來從請求對象接收回調通知的句柄函數
      var handlerFunction =
      getReadyStateHandler(req, updateCart);
      req.onreadystatechange =
      handlerFunction;
      // 打開一個聯接到購物車servlet的
      HTTP POST聯接
      // 第三個參數表示請求是異步的
      req.open("POST", "cart.do", true);
    // 指示請求體包含form數據
      req.setRequestHeader("Content-Type",
     "application/x-www-form-urlencoded");
    // 發送標志需要添加到購物車
    中條目的form-encoded數據
    req.send("action=add&item="+itemCode);
    }

    結合以上內容,你可以了解到Ajax處理過程的第一部分—就是在客戶端創建并發送HTTP請求。下一步是用來處理請求的Java Servlet代碼。

    Servlet請求處理

    通過一個servlet來處理XMLHttpRequest與處理一個來自瀏覽器的普通的HTTP請求基本上相似?梢酝ㄟ^調用HttpServletRequest.getParameter()來獲取由POST請求體傳送過來的form-encoded數據。

    Ajax請求也與普通的WEB請求樣都成為此應用同一HttpSession會話進程的一部分。這對于購物車例子來說很有肜,因為我們可以通過會話將多個請求的狀態都保存到同一個JavaBean購物車對象中,并可以序列化。

    列表4是處理Ajax請求并更新購物車的簡單servlet的代碼片斷。從用戶會話中檢索出一個Cart Bean,并按請求的參數更新它。之后Cart Bean被序列化到XML,并被寫回ServletRespone。注意,一定要將響應內容的類型設置為application/xml,否則,XMLHttpRequest將不能將響應內容解析為一個XML DOM。

    列表4:處理Ajax請求的Servlet代碼

    public void doPost(HttpServletRequest req,
    HttpServletResponse res)
    throws Java.io.IOException
    {
     Cart cart = getCartFromSession(req);
    String action = req.getParameter("action");
    String item = req.getParameter("item");
    if ((action != null)&&(item != null))
    {
        // 在購物車中添加或移除一個條目
        if ("add".equals(action))
     {
          cart.addItem(item);
        } else if ("remove".equals(action))  {
          cart.removeItems(item);
        }
      }
      // 將購物車狀態序列化到XML
      String cartXml = cart.toXml();
      // 將XML寫入response.
      res.setContentType("application/xml");
      res.getWriter().write(cartXml);
    }

    列表5展示了由Cart.toXml()方法生成的XML。注意到生成的cart元素的屬性,是一個通過System.currentTimeMillis()生成的時間戳。

    列表5:Cart對象序列化得到的XML

    <?xml version="1.0"?>
    <cart generated="1123969988414"
    total="$171.95">
      <item code="hat001">
        <name>Hat</name>
        <quantity>2</quantity>
      </item>
      <item code="cha001">
        <name>Chair</name>
        <quantity>1</quantity>
      </item>
      <item code="dog001">
        <name>Dog</name>
        <quantity>1</quantity>
      </item>
    </cart>

    如果你觀察一下下載站點提供的例子應用源碼中的Cart.Java,你將會看到它通過簡單地追加字符串來生成XML。對于本例子來說,它已經足夠了,我將會在本系統文章的以后一期中介紹一些更好的方法。

    現在你知道了CartServlet如何響應一個XMLHttpRequest。下一步是返回到客戶端,如何用服務器響應來更新頁面狀態。

    通過JavaScript來處理服務器響應

    XMLHttpRequest的readyState屬性是一個給出請求生命周期狀態的數字值。它從表示“未初始化”的0變化到表示“完成”的4。每次readyState改變時,都會引發readystatechange事件,通過onreadystatechange屬性配置回調處理函數將會被調用。

    在列表3中,你已看到通過調用函數getReadyStateHandler()創建了一個處理函數,并被配置給onreadystatechange屬性。getReadyStateHandler()使用了這樣的事實:函數是JavaScript中的主要對象。

    這意味著,函數可以作為參數被傳遞到其它函數,并且可以創建并返回其它函數。getReadystateHandler()要做是就是返回一個函數,來檢查XMLHttpRequet是否已經完成處理,并傳遞XML服務器響應到由調用者指定的處理函數。列表6是getReadyStateHandler()的代碼。

    列表6:函數getReadyStateHandler()

    /*
     * Returns a function that waits for
     the specified XMLHttpRequest
     * to complete, then passes its XML
     response to the given handler function.
     * req - The XMLHttpRequest
     whose state is changing
     * responseXmlHandler -
     Function to pass the XML response to
     */
    function getReadyStateHandler(req,
    responseXmlHandler) {
      // 返回一個監聽XMLHttpRequest實例的匿名函數
      return function ()
      {
        // 如果請求的狀態是“完成”
        if (req.readyState == 4)
     {
          // 檢查是否成功接收了服務器響應
          if (req.status == 200)
       {
            // 將載有響應信息的XML傳遞到處理函數
            responseXmlHandler(req.responseXML);
          } else
       {
            // 有HTTP問題發生
            alert("HTTP error: "+req.status);
          }
        }
      }
    }

    HTTP狀態碼

    在列表6中,XMLHttpRequest的status屬性被測試用來確定請求是否成功完成。當處理簡單的GET與POST請求,你可以認為只要不是200(OK)的狀態就表示發生了錯誤。若服務器發送了一個重定向響應(例如,301或302),瀏覽器會透明地完成重定向并從新位置獲取相應的資源;XMLHttpRequest不會看到重定向狀態碼。

    同時,瀏覽器自動添加一個緩存控制:對于所有XMLHttpRequest都使用no-cache header,這樣客戶端代碼就可以不用處理304(not-modified)響應。

    關于getReadyStateHandler()

    getReadyStateHandler()是相對比較復雜的一段代碼,特別當你不能熟悉閱讀JavaScript時。折中方案是在你的JavaScript庫中包含此函數,你可以簡單地處理Ajax服務器響應,而不用去注意XMLHttpRequest的內部細節。重要是你自己要理解在代碼中如何使用getReadyStateHandler()。

    在列表3中,你看到getReadyStateHandler()被這樣調用:

    handlerFunction=
    getReadyStateHandler(req,updateCart)

    由它返回的函數將會檢查在req變量中的XMLHttpRequest是否已完成,并調用由updateCart指定的回調方法處理響應XML。

    提取購物車數據

    列表7中展示了updateCart()中的代碼。此函數使用DOM來解析購物車XML文檔,并更新WEB頁面(參見列表1)來反映新的購物車內容。注意對用來提取數據的XML DOM的調用。

    Cart元素上生成的屬性,即序列化時生成的時間戳,通過檢測它可以保證不會用老的數據來覆蓋新的購物車數據。Ajax請求天生就是異步的,通過這個檢測可以有效避免在過程外到達的服務器響應的干擾。

    列表7:更新頁面來反映出購物車XML文檔內容

    function updateCart(cartXML)
    {
     // 從文檔中獲取根元素“cart”
     var cart =
     cartXML.getElementsByTagName("cart")[0];
     // 保證此文檔是最新的
     var generated =
     cart.getAttribute("generated");
     if (generated > lastCartUpdate)
     {
       lastCartUpdate = generated;
    // 清除HTML列表,用來顯示購物車內容
    var contents =
    document.getElementById("cart-contents");
    contents.innerHTML = "";
    // 在購物車內按條目循環
       var items =
       cart.getElementsByTagName("item");
       for (var I = 0 ;
       I < items.length ; I++)
       {
         var item = items[I];
         // 從name與quantity元素中提取文本節點
         var name = item.getElementsByTagName("name")
      [0].firstChild.nodeValue;
         var quantity = item.getElementsByTagName
      ("quantity")[0].firstChild.nodeValue;
         // 為條目創建并添加到HTML列表中
         var li = document.createElement("li");
         li.appendChild
      (document.createTextNode(name+" x "+quantity));
         contents.appendChild(li);
       }
     }
     // 更新購物車的金額累計
     document.getElementById("total").innerHTML = cart.getAttribute("total");
    }

    到現在,關于Ajax處理過程的教程已經結束,也許你想讓應用運行起來,并看看它的實際運作。這個例子非常簡單,有非常大的改進的余地。比如,我在服務器端代碼中包含了從購物車中移除條目的代碼,但從客戶端UI中沒有訪問的途徑。作為一個練習,嘗試在現有的JavaScript基礎上實際這個功能。

    使用Ajax的挑戰

    與任何技術一樣,使用Ajax在相當多的方面都可能范錯誤。我在這兒討論的問題目前都缺少解決方案,并將會隨著Ajax的成熟而解決或提高。隨著開發Ajax應用經驗的不斷獲取,開發者社區中將會出現最好的實踐經驗與指導方針。

    XMLHttpRequest的有效性

    Ajax開發者面對的一個最大問題是當XMLHttpRequest不可用時如何反應。雖然大部分現代瀏覽器支持XMLHttpRequest,但還是有少量的用戶,他們的瀏覽器不能支持,或由于瀏覽器安全設置而阻止對XMLHttpRequest的使用。

    若你的Web應用發布于公司內部的Intranet上,你很可能可以指定支持哪種瀏覽器,并可以確保XMLHttpRequest是可用的。若你在公共WEB上發布,則你必須意識到由于假定XMLHttpRequest是可用的,所有就阻止了老瀏覽器、手持設備瀏覽器等等用戶來使用你的系統。

    然而,你應該盡力保證應用系統“正常降級”使用,在系統中保留適用于不支持XMLHttpRequest的瀏覽器的功能。在購物車例子中,最好的方法是有一個Add to Cart按鈕,可以進行常規的提交處理,并刷新頁面來反映購物車狀態的變化。

    Ajax行衛可以在頁面被載入時通過JavaScript添加到頁面中,只在XMLHttpRequest可用的情況下,為每個Add to Cart按鈕加上JavaScript處理函數。另一個方法是在用戶登錄時檢測XMLHttpRequest,再決定是提供Ajax版本還是常規基于form提交的版本。

    可用性考慮

    圍繞著Ajax應用的大部分問題都是很普通的問題。例如,讓用戶知道他們的輸入已經被注冊并處理,是很重要的,因為在XMLHttpRequest處理過程中并不能提供通常的漏斗旋轉光標。一種方法是將“確認”按扭上的文本替換為“正在更新中…”,以避免用戶在等待響應時多次點擊按鈕。

    另一個問題是,用戶可能沒有注意到他們正在觀看的頁面已經被更新?梢酝ㄟ^使用各種視覺技巧來將用戶的眼光吸引到頁面的更新區域。還有一個問題是通過Ajax更新頁面打斷了瀏覽器“退回前頁”按鈕的正常工作,地址欄中的URL不能反映頁面的全部狀態,并且不能使用書簽功能。參見Resource章節中列出的網站地址上的文章來了解更多Ajax應用關于可用性方面的問題。

    服務器負載

    使用Ajax界面代替傳統的基于form的界面可能戲劇性地增加傳遞到服務器的請求數量。例如,一個普通的Google搜索給服務器造成一次命中,并在用戶確認搜索表單時發生。然而,Google Suggest,將會試圖自動完成你的搜索詞,在用戶打字時將會往服務器發送多個請求。

    在開發一個Ajax應用時,要注意到你將會發送多少請求到用戶器端,以及服務器的負載指標。你可以通過在客戶端適當地緩存請求、與服務器響應來緩減負載壓力。你也應該在設計Ajax應用時盡量在客戶端處理更多的邏輯,而不用與服務器端通訊。

    處理異步

    一定要記住,沒有任何東西可以保證XMLHttpRequest將會按照它們被發送的順序來依次結束。實際上,你在設計系統時,腦子里應該始終假定它們不會按原來順序結束。在購物車例子中,使用了一個最后更新的時間戳來保證最新的數據不會被改寫。

    這個非;镜姆椒ǹ梢栽谫徫镘噲鼍爸泄ぷ,但可能不能在其它情況下工作。在設計時刻就要考慮你該如何處理異步服務器響應。

    結論

    你現在應該對于Ajax的基本原則有了一個良好的了解,另外,你應該理解一些更高級的隨Ajax方法而來的設計問題。創建一個成功的Ajax應用需要一系列的方法—從JavaScript UI設計到服務器端架構—但是你現在應該已經具備了需要使用到的Ajax核心知識。

    延伸閱讀

    文章來源于領測軟件測試網 http://www.kjueaiud.com/

    TAG: ajax web 道路 更好 開發 鋪設 應用


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備10010545號-5
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>