欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
面向 Java 開(kāi)發(fā)人員的 Ajax: 結合 Direct Web Remoting 使用 Ajax

Philip McCarthy, 軟件開(kāi)發(fā)顧問(wèn), Independent Consultant

2005 年 12 月 27 日

雖然令人興奮,但是把 Ajax 功能添加到應用程序可能意味著(zhù)大量的艱苦工作。在面向 Java? 開(kāi)發(fā)人員的 Ajax 系列的第 3 篇文章中,Philip McCarthy 介紹了如何使用Direct Web Remoting(DWR)直接把 JavaBean 的方法公開(kāi)給 JavaScript 代碼并自動(dòng)進(jìn)行 Ajax 的繁重工作。

理解 Ajax 編程的基本知識 是重要的,但是如果正在構建復雜的用戶(hù)界面,那么能夠在更高層次的抽象上工作也很重要。在面向 Java 開(kāi)發(fā)人員的 Ajax 系列的第 3 篇文章中,我在上個(gè)月的 Ajax 的數據序列化技術(shù) 基礎之上,介紹一種可以避免繁瑣的 Java 對象序列化細節的技術(shù)。

上一篇文章 中,我介紹了如何用 JavaScript 對象標注(JSON)以一種在客戶(hù)機上容易轉化成 JavaScript 對象的格式對數據進(jìn)行序列化。有了這個(gè)設置,就可以用 JavaScript 代碼調用遠程服務(wù),并在響應中接收 JavaScript 對象圖,但是又不像遠程過(guò)程調用。這一次,將學(xué)習如何更進(jìn)一步,使用一個(gè)框架,把從 JavaScript 客戶(hù)代碼對服務(wù)器端 Java 對象進(jìn)行遠程調用的能力正式化。

DWR 是一個(gè)開(kāi)放源碼的使用 Apache 許可協(xié)議的解決方案,它包含服務(wù)器端 Java 庫、一個(gè) DWR servlet 以及 JavaScript 庫。雖然 DWR 不是 Java 平臺上唯一可用的 Ajax-RPC 工具包,但是它是最成熟的,而且提供了許多有用的功能。請參閱 參考資料,在繼續學(xué)習之前下載 DWR。

DWR 是什么?

從最簡(jiǎn)單的角度來(lái)說(shuō),DWR 是一個(gè)引擎,可以把服務(wù)器端 Java 對象的方法公開(kāi)給 JavaScript 代碼。使用 DWR 可以有效地從應用程序代碼中把 Ajax 的全部請求-響應循環(huán)消除掉。這意味著(zhù)客戶(hù)端代碼再也不需要直接處理 XMLHttpRequest 對象或者服務(wù)器的響應。不再需要編寫(xiě)對象的序列化代碼或者使用第三方工具才能把對象變成 XML。甚至不再需要編寫(xiě) servlet 代碼把 Ajax 請求調整成對 Java 域對象的調用。

DWR 是作為 Web 應用程序中的 servlet 部署的。把它看作一個(gè)黑盒子,這個(gè) servlet 有兩個(gè)主要作用:首先,對于公開(kāi)的每個(gè)類(lèi),DWR 動(dòng)態(tài)地生成包含在 Web 頁(yè)面中的 JavaScript。生成的 JavaScript 包含存根函數,代表 Java 類(lèi)上的對應方法并在幕后執行 XMLHttpRequest。這些請求被發(fā)送給 DWR,這時(shí)它的第二個(gè)作用就是把請求翻譯成服務(wù)器端 Java 對象上的方法調用并把方法的返回值放在 servlet 響應中發(fā)送回客戶(hù)端,編碼成 JavaScript。DWR 還提供了幫助執行常見(jiàn)的用戶(hù)界面任務(wù)的 JavaScript 工具函數。





回頁(yè)首


關(guān)于示例

在更詳細地解釋 DWR 之前,我要介紹一個(gè)簡(jiǎn)單的示例場(chǎng)景。像在前一篇文章中一樣,我將采用一個(gè)基于在線(xiàn)商店的最小模型,這次包含一個(gè)基本的產(chǎn)品表示、一個(gè)可以包含產(chǎn)品商品的用戶(hù)購物車(chē)以及一個(gè)從數據存儲查詢(xún)產(chǎn)品的數據訪(fǎng)問(wèn)對象(DAO)。Item 類(lèi)與前一篇文章中使用的一樣,但是不再實(shí)現任何手工序列化方法。圖 1 說(shuō)明了這個(gè)簡(jiǎn)單的設置:


圖 1. 說(shuō)明 Cart、CatalogDAO 和 Item 類(lèi)的類(lèi)圖

在這個(gè)場(chǎng)景中,我將演示兩個(gè)非常簡(jiǎn)單的用例。第一,用戶(hù)可以在目錄中執行文本搜索并查看匹配的商品。第二,用戶(hù)可以添加商品到購物車(chē)中并查看購物車(chē)中商品的總價(jià)。





回頁(yè)首


實(shí)現目錄

DWR 應用程序的起點(diǎn)是編寫(xiě)服務(wù)器端對象模型。在這個(gè)示例中,我從編寫(xiě) DAO 開(kāi)始,用它提供對產(chǎn)品目錄數據存儲的搜索功能。CatalogDAO.java 是一個(gè)簡(jiǎn)單的無(wú)狀態(tài)的類(lèi),有一個(gè)無(wú)參數的構造函數。清單 1 顯示了我想要公開(kāi)給 Ajax 客戶(hù)的 Java 方法的簽名:


清單 1. 通過(guò) DWR 公開(kāi)的 CatalogDAO 方法
                        /**                        * Returns a list of items in the catalog that have                        *  names or descriptions matching the search expression                        * @param expression Text to search for in item names                        *  and descriptions                        * @return list of all matching items                        */                        public List<Item> findItems(String expression);                        /**                        * Returns the Item corresponding to a given Item ID                        * @param id The ID code of the item                        * @return the matching Item                        */                        public Item getItem(String id);                        

接下來(lái),我需要配置 DWR,告訴它 Ajax 客戶(hù)應當能夠構建 CatalogDAO 并調用這些方法。我在清單 2 所示的 dwr.xml 配置文件中做這些事:


清單 2. 公開(kāi) CatalogDAO 方法的配置
                        <!DOCTYPE dwr PUBLIC                        "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"                        "http://www.getahead.ltd.uk/dwr/dwr10.dtd">                        <dwr>                        <allow>                        <create creator="new" javascript="catalog">                        <param name="class"                        value="developerworks.ajax.store.CatalogDAO"/>                        <include method="getItem"/>                        <include method="findItems"/>                        </create>                        <convert converter="bean"                        match="developerworks.ajax.store.Item">                        <param name="include"                        value="id,name,description,formattedPrice"/>                        </convert>                        </allow>                        </dwr>                        

dwr.xml 文檔的根元素是 dwr。在這個(gè)元素內是 allow 元素,它指定 DWR 進(jìn)行遠程的類(lèi)。allow 的兩個(gè)子元素是 createconvert。

create 元素

create 元素告訴 DWR 應當公開(kāi)給 Ajax 請求的服務(wù)器端類(lèi),并定義 DWR 應當如何獲得要進(jìn)行遠程的類(lèi)的實(shí)例。這里的 creator 屬性被設置為值 new,這意味著(zhù) DWR 應當調用類(lèi)的默認構造函數來(lái)獲得實(shí)例。其他的可能有:通過(guò)代碼段用 Bean 腳本框架(Bean Scripting Framework,BSF)創(chuàng )建實(shí)例,或者通過(guò)與 IOC 容器 Spring 進(jìn)行集成來(lái)獲得實(shí)例。默認情況下,到 DWR 的 Ajax 請求會(huì )調用 creator,實(shí)例化的對象處于頁(yè)面范圍內,因此請求完成之后就不再可用。在無(wú)狀態(tài)的 CatalogDAO 情況下,這樣很好。

createjavascript 屬性指定從 JavaScript 代碼訪(fǎng)問(wèn)對象時(shí)使用的名稱(chēng)。嵌套在 create 元素內的 param 元素指定 creator 要創(chuàng )建的 Java 類(lèi)。最后,include 元素指定應當公開(kāi)的方法的名稱(chēng)。顯式地說(shuō)明要公開(kāi)的方法是避免偶然間允許訪(fǎng)問(wèn)有害功能的良好實(shí)踐 —— 如果漏了這個(gè)元素,類(lèi)的所有方法都會(huì )公開(kāi)給遠程調用。反過(guò)來(lái),可以用 exclude 元素指定那些想防止被訪(fǎng)問(wèn)的方法。

convert 元素

creator 負責公開(kāi)用于 Web 遠程的類(lèi)和類(lèi)的方法,convertor 則負責這些方法的參數和返回類(lèi)型。convert 元素的作用是告訴 DWR 在服務(wù)器端 Java 對象表示和序列化的 JavaScript 之間如何轉換數據類(lèi)型。

DWR 自動(dòng)地在 Java 和 JavaScript 表示之間調整簡(jiǎn)單數據類(lèi)型。這些類(lèi)型包括 Java 原生類(lèi)型和它們各自的類(lèi)表示,還有 String、Date、數組和集合類(lèi)型。DWR 也能把 JavaBean 轉換成 JavaScript 表示,但是出于安全性的原因,做這件事要求顯式的配置。

清單 2 中的 convert 元素告訴 DWR 用自己基于反射的 bean 轉換器處理 CatalogDAO 的公開(kāi)方法返回的 Item,并指定序列化中應當包含 Item 的哪個(gè)成員。成員的指定采用 JavaBean 命名規范,所以 DWR 會(huì )調用對應的 get 方法。在這個(gè)示例中,我去掉了數字的 price 字段,而是包含了 formattedPrice 字段,它采用貨幣格式進(jìn)行顯示。

現在,我準備把 dwr.xml 部署到 Web 應用程序的 WEB-INF 目錄,在那里 DWR servlet 會(huì )讀取它。但是,在繼續之前,確保每件事都按照希望的那樣運行是個(gè)好主意。





回頁(yè)首


測試部署

如果 DWRServletweb.xml 定義把 init-param debug 設置為 true,那么就啟用了 DWR 非常有幫助的測試模式。導航到 /{your-web-app}/dwr/ 會(huì )把 DWR 配置的要進(jìn)行遠程的類(lèi)列表顯示出來(lái)。在其中點(diǎn)擊,會(huì )進(jìn)入指定類(lèi)的狀態(tài)屏幕。CatalogDAO 的 DWR 測試頁(yè)如圖 2 所示。除了提供粘貼到 Web 頁(yè)面的 script 標記(指向 DWR 為類(lèi)生成的 JavaScript)之外,這個(gè)屏幕還提供了類(lèi)的方法列表。這個(gè)列表包括從類(lèi)的超類(lèi)繼承的方法,但是只有在 dwr.xml 中顯式地指定為遠程的才標記為可訪(fǎng)問(wèn)。


圖 2. CatalogDAO 的 DWR 測試頁(yè)

可以在可訪(fǎng)問(wèn)的方法旁邊的文本框中輸入參數值并點(diǎn)擊 Execute 按鈕調用方法。服務(wù)器的響應將在警告框中用 JSON 標注顯示出來(lái),如果是簡(jiǎn)單值,就會(huì )內聯(lián)在方法旁邊直接顯示。這個(gè)測試頁(yè)非常有用。它們不僅允許檢查公開(kāi)了哪個(gè)類(lèi)和方法用于遠程,還可以測試每個(gè)方法是否像預期的那樣工作。

如果對遠程方法的工作感到滿(mǎn)意,就可以用 DWR 生成的 JavaScript 存根從客戶(hù)端代碼調用服務(wù)器端對象。





回頁(yè)首


調用遠程對象

遠程 Java 對象方法和對應的 JavaScript 存根函數之間的映射很簡(jiǎn)單。通用的形式是 JavaScriptName.methodName(methodParams ..., callBack),其中 JavaScriptNamecreatorjavascript 屬性指定的名稱(chēng),methodParams 代表 Java 方法的 n 個(gè)參數,callback 是要用 Java 方法的返回值調用的 JavaScript 函數。如果熟悉 Ajax,可以看出這個(gè)回調機制是 XMLHttpRequest 異步性的常用方式。

在示例場(chǎng)景中,我用清單 3 中的 JavaScript 函數執行搜索,并用搜索結果更新用戶(hù)界面。這個(gè)清單還使用來(lái)自 DWR 的 util.js 的便捷函數。要特別說(shuō)明的是名為 $() 的 JavaScript 函數,可以把它當作 document.getElementById() 的加速版。錄入它當然更容易。如果您使用過(guò) JavaScript 原型庫,應當熟悉這個(gè)函數。


清單 3. 從客戶(hù)機調用遠程的 findItems()
                        /*                        * Handles submission of the search form                        */                        function searchFormSubmitHandler() {                        // Obtain the search expression from the search field                        var searchexp = $("searchbox").value;                        // Call remoted DAO method, and specify callback function                        catalog.findItems(searchexp, displayItems);                        // Return false to suppress form submission                        return false;                        }                        /*                        * Displays a list of catalog items                        */                        function displayItems(items) {                        // Remove the currently displayed search results                        DWRUtil.removeAllRows("items");                        if (items.length == 0) {                        alert("No matching products found");                        $("catalog").style.visibility = "hidden";                        } else {                        DWRUtil.addRows("items",items,cellFunctions);                        $("catalog").style.visibility = "visible";                        }                        }

在上面的 searchFormSubmitHandler() 函數中,我們感興趣的代碼當然是 catalog.findItems(searchexp, displayItems);。這一行代碼就是通過(guò)網(wǎng)絡(luò )向 DWR servlet 發(fā)送 XMLHttpRequest 并用遠程對象的響應調用 displayItems() 函數所需要的全部?jì)热荨?/p>

displayItems() 回調本身是由一個(gè) Item 數組表示調用的。這個(gè)數組傳遞給 DWRUtil.addRows() 便捷函數,同時(shí)還有要填充的表的 ID 和一個(gè)函數數組。表中每行有多少單元格,這個(gè)數組中就有多少個(gè)函數。按照順序使用來(lái)自數組的 Item 逐個(gè)調用每個(gè)函數,并用返回的內容填充對應的單元格。

在這個(gè)示例中,我想讓商品表中的每一行都顯示商品的名稱(chēng)、說(shuō)明和價(jià)格,并在最后一列顯示商品的 Add to Cart 按鈕。清單 4 顯示了實(shí)現這一功能的單元格函數數組:


清單 4. 填充商品表的單元格函數數組
                        /*                        * Array of functions to populate a row of the items table                        * using DWRUtil‘s addRows function                        */                        var cellFunctions = [                        function(item) { return item.name; },                        function(item) { return item.description; },                        function(item) { return item.formattedPrice; },                        function(item) {                        var btn = document.createElement("button");                        btn.innerHTML = "Add to cart";                        btn.itemId = item.id;                        btn.onclick = addToCartButtonHandler;                        return btn;                        }                        ];                        

前三個(gè)函數只是返回 dwr.xml 中 Itemconvertor 包含的字段內容。最后一個(gè)函數創(chuàng )建一個(gè)按鈕,把 Item 的 ID 賦給它,并指定在點(diǎn)擊按鈕時(shí)應當調用名為 addToCartButtonHandler 的函數。這個(gè)函數是第二個(gè)用例的入口點(diǎn):向購物車(chē)中添加 Item。





回頁(yè)首


實(shí)現購物車(chē)

DWR 的安全性

DWR 設計時(shí)就考慮了安全性。使用 dwr.xml 明確地列出那些想做遠程處理的類(lèi)和方法,可以避免意外地把那些可能被惡意利用的功能公開(kāi)出去。除此之外,使用調試測試模式,可以容易地審計所有公開(kāi)到 Web 上的類(lèi)和方法。

DWR 也支持基于角色的安全性。通過(guò) bean 的 creator 配置,可以指定用戶(hù)訪(fǎng)問(wèn)特定 bean 所必須屬于的 J2EE 角色。通過(guò)部署多個(gè) URL 受保護的 DWRServlet 實(shí)例,每個(gè)實(shí)例都有自己的 dwr.xml 配置文件,也可以提供擁有不同遠程功能的用戶(hù)集。

用戶(hù)購物車(chē)的 Java 表示基于 Map。當 Item 添加到購物車(chē)中時(shí),Item 本身作為鍵被插入 Map。 Map 中對應的值是一個(gè) Integer,代表購物車(chē)中指定 Item 的數量。所以 Cart.java 有一個(gè)字段 contents,聲明為 Map<Item,Integer>。

使用復雜類(lèi)型作為哈希鍵給 DWR 帶來(lái)一個(gè)問(wèn)題 —— 在 JavaScript 中,數組的鍵必須是標量的。所以,DWR 無(wú)法轉換 contents Map。但是,對于購物車(chē)用戶(hù)界面來(lái)說(shuō),用戶(hù)需要查看的只是每個(gè)商品的名稱(chēng)和數量。所以我向 Cart 添加了一個(gè)名為 getSimpleContents() 的方法,它接受 contents Map 并根據它構建一個(gè)簡(jiǎn)化的 Map<String,Integer>,只代表每個(gè) Item 的名稱(chēng)和數量。這個(gè)用字符串作為鍵的 map 表示可以由 DWR 的轉換器轉換成 JavaScript。

客戶(hù)對 Cart 感興趣的其他字段是 totalPrice,它代表購物車(chē)中所有商品的金額匯總。使用 Item,我還提供了一個(gè)合成的成員叫作 formattedTotalPrice,它是金額匯總的格式化好的 String 表示。

轉換購物車(chē)

為了不讓客戶(hù)代碼對 Cart 做兩個(gè)調用(一個(gè)獲得內容,一個(gè)獲得總價(jià)),我想把這些數據一次全都發(fā)給客戶(hù)。為了做到這一點(diǎn),我添加了一個(gè)看起來(lái)有點(diǎn)兒怪的方法,如清單 5 所示:


清單 5. Cart.getCart() 方法
                        /**                        * Returns the cart itself - for DWR                        * @return the cart                        */                        public Cart getCart() {                        return this;                        }                        

雖然這個(gè)方法在普通的 Java 代碼中可能完全是多余的(因為在調用這個(gè)方法時(shí),已經(jīng)有對 Cart 的引用),但它允許 DWR 客戶(hù)讓 Cart 把自己序列化成 JavaScript。

除了 getCart(),需要遠程化的另一個(gè)方法是 addItemToCart()。這個(gè)方法接受目錄 Item 的 ID 的 String 表示,把這個(gè)商品添加到 Cart 中并更新總價(jià)。方法還返回 Cart,這樣客戶(hù)代碼在一個(gè)操作中就能更新 Cart 的內容并接收購物車(chē)的新?tīng)顟B(tài)。

清單 6 是擴展的 dwr.xml 配置文件,包含 Cart 類(lèi)進(jìn)行遠程所需要的額外配置:


清單 6. 修改過(guò)的 dwr.xml 包含了 Cart 類(lèi)
                        <!DOCTYPE dwr PUBLIC                        "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"                        "http://www.getahead.ltd.uk/dwr/dwr10.dtd">                        <dwr>                        </allow>                        </create creator="new" javascript="catalog">                        </param name="class"                        value="developerworks.ajax.store.CatalogDAO"/>                        </include method="getItem"/>                        </include method="findItems"/>                        <//create>                        </convert converter="bean"                        match="developerworks.ajax.store.Item">                        </param name="include"                        value="id,name,description,formattedPrice"/>                        <//convert>                            </create creator="new" scope="session" javascript="Cart">                        </param name="class"                        value="developerworks.ajax.store.Cart"/>                        </include method="addItemToCart"/>                        </include method="getCart"/>                        <//create>                        </convert converter="bean"                        match="developerworks.ajax.store.Cart">                        </param name="include"                        value="simpleContents,formattedTotalPrice"/>                        <//convert>                          <//allow>                        </dwr>                        

在這個(gè)版本的 dwr.xml 中,我添加了 Cartcreatorconvertor。create 元素指定應當把 addItemToCart()getCart() 方法遠程化,而且重要的是,生成的 Cart 實(shí)例應當放在用戶(hù)的會(huì )話(huà)中。所以,購物車(chē)的內容在用戶(hù)的請求之間會(huì )保留。

Cartconvert 元素是必需的,因為遠程的 Cart 方法返回的是 Cart 本身。在這里我指定在 Cart 的序列化 JavaScript 形式中應當存在的成員是 simpleContents 這個(gè)圖和 formattedTotalPrice 這個(gè)字符串。

如果對這覺(jué)得有點(diǎn)兒不明白,那么只要記住 create 元素指定的是 DWR 客戶(hù)可以調用的 Cart 服務(wù)器端方法,而 convert 元素指定在 Cart 的 JavaScript 序列化形式中包含的成員。

現在可以實(shí)現調用 Cart 的遠程方法的客戶(hù)端代碼了。





回頁(yè)首


調用遠程的 Cart 方法

首先,當商店的 Web 頁(yè)首次裝入時(shí),我想檢查保存在會(huì )話(huà)中的 Cart 的狀態(tài),看是否已經(jīng)有一個(gè)購物車(chē)了。這是必需的,因為用戶(hù)可能已經(jīng)向 Cart 中添加了商品,然后刷新了頁(yè)面或者導航到其他地方之后又返回來(lái)。在這些情況下,重新載入的頁(yè)面需要用會(huì )話(huà)中的 Cart 數據對自己進(jìn)行同步。我可以在頁(yè)面的 onload 函數中用一個(gè)調用做到這一點(diǎn),就像這樣:Cart.getCart(displayCart)。請注意 displayCart() 是一個(gè)回調函數,由服務(wù)器返回的 Cart 響應數據調用。

如果 Cart 已經(jīng)在會(huì )話(huà)中,那么creator 會(huì )檢索它并調用它的 getCart() 方法。如果會(huì )話(huà)中沒(méi)有 Cart,那么 creator 會(huì )實(shí)例化一個(gè)新的,把它放在會(huì )話(huà)中,并調用 getCart() 方法。

清單 7 顯示了 addToCartButtonHandler() 函數的實(shí)現,當點(diǎn)擊商品的 Add to Cart 按鈕時(shí)會(huì )調用這個(gè)函數:


清單 7. addToCartButtonHandler() 實(shí)現
                        /*                        * Handles a click on an Item‘s "Add to Cart" button                        */                        function addToCartButtonHandler() {                        // ‘this‘ is the button that was clicked.                        // Obtain the item ID that was set on it, and                        // add to the cart.                        Cart.addItemToCart(this.itemId,displayCart);                        }                        

由 DWR 負責所有通信,所以客戶(hù)上的添加到購物車(chē)行為就是一個(gè)函數。清單 8 顯示了這個(gè)示例的最后一部分 —— displayCart() 回調的實(shí)現,它用 Cart 的狀態(tài)更新用戶(hù)界面:


清單 8. displayCart() 實(shí)現
                        /*                        * Displays the contents of the user‘s shopping cart                        */                        function displayCart(cart) {                        // Clear existing content of cart UI                        var contentsUL = $("contents");                        contentsUL.innerHTML="";                        // Loop over cart items                        for (var item in cart.simpleContents) {                        // Add a list element with the name and quantity of item                        var li = document.createElement("li");                        li.appendChild(document.createTextNode(                        cart.simpleContents[item] + " x " + item                        ));                        contentsUL.appendChild(li);                        }                        // Update cart total                        var totalSpan = $("totalprice");                        totalSpan.innerHTML = cart.formattedTotalPrice;                        }                        

在這里重要的是要記住,simpleContents 是一個(gè)把 String 映射到數字的 JavaScript 數組。每個(gè)字符串都是一個(gè)商品的名稱(chēng),關(guān)聯(lián)數組中的對應數字就是購物車(chē)中該商品的數量。所以表達式 cart.simpleContents[item] + " x " + item 可能就會(huì )計算出 “2 x Oolong 128MB CF Card” 這樣的結果。

DWR 商店應用程序

圖 3 顯示了這個(gè)基于 DWR 的 Ajax 應用程序的使用情況:顯示了通過(guò)搜索檢索到的商品,并在右側顯示用戶(hù)的購物車(chē):


圖 3. 基于 DWR 的 Ajax 商店應用程序的使用情況





回頁(yè)首


DWR 的利弊

調用批處理

在 DWR 中,可以在一個(gè) HTTP 請求中向服務(wù)器發(fā)送多個(gè)遠程調用。調用 DWREngine.beginBatch() 告訴 DWR 不要直接分派后續的遠程調用,而是把它們組合到一個(gè)批請求中。DWREngine.endBatch() 調用則把批請求發(fā)送到服務(wù)器。遠程調用在服務(wù)器端順序執行,然后調用每個(gè) JavaScript 回調。

批處理在兩方面有助于降低延遲:第一,避免了為每個(gè)調用創(chuàng )建 XMLHttpRequest 對象并建立相關(guān)的 HTTP 連接的開(kāi)銷(xiāo)。第二,在生產(chǎn)環(huán)境中,Web 服務(wù)器不必處理過(guò)多的并發(fā) HTTP 請求,改進(jìn)了響應時(shí)間。

現在可以看出用 DWR 實(shí)現由 Java 支持的 Ajax 應用程序有多么容易了。雖然示例場(chǎng)景很簡(jiǎn)單,我實(shí)現用例的手段也盡可能少,但是不應因此而低估 DWR 引擎相對于自己設計 Ajax 應用程序可以節約的工作量。在前一篇文章中,我介紹了手工設計 Ajax 請求和響應、把 Java 對象圖轉化成 JSON 表示的全部步驟,在這篇文章中,DWR 替我做了所有這些工作。我只編寫(xiě)了不到 50 行 JavaScript 就實(shí)現了客戶(hù)機,而在服務(wù)器端,我需要做的所有工作就是給常規的 JavaBean 加上一些額外方法。

當然,每種技術(shù)都有它的不足。同任何 RPC 機制一樣,在 DWR 中,可能很容易忘記對于遠程對象進(jìn)行的每個(gè)調用都要比本地函數調用昂貴得多。DWR 在隱藏 Ajax 的機械性方面做得很好,但是重要的是要記住網(wǎng)絡(luò )并不是透明的 —— 進(jìn)行 DWR 調用會(huì )有延遲,所以應用程序的架構應當讓遠程方法的粒度比較粗。正是為了這個(gè)目的,addItemToCart() 才返回 Cart 本身。雖然讓 addItemToCart() 作為一個(gè) void 方法可能更自然,但是這樣的話(huà)對它的每個(gè) DWR 調用后面都必須跟著(zhù)一個(gè) getCart() 調用以檢索修改后的 Cart 狀態(tài)。

對于延遲,DWR 在調用的批處理中有自己的解決方案(請參閱側欄的 調用批處理)。如果不能為應用程序提供適當粗粒度的 Ajax 接口,那么只要有可能把多個(gè)遠程調用組合到一個(gè) HTTP 請求中,就請使用調用批處理。

分離的問(wèn)題

從實(shí)質(zhì)上看,DWR 在客戶(hù)端和服務(wù)器端代碼間形成了緊密的耦合,這有許多含義:首先,遠程方法 API 的變化需要在 DWR 存根調用的 JavaScript 上反映出來(lái)。第二(也是最明顯的),這種耦合會(huì )造成對客戶(hù)端的考慮會(huì )滲入服務(wù)器端代碼。例如,因為不是所有 Java 類(lèi)型都能轉化成 JavaScript,所以有時(shí)有必要給 Java 對象添加額外方法,好讓它能夠更容易地遠程化。在示例場(chǎng)景中,我通過(guò)把 getSimpleContents() 方法添加到 Cart 來(lái)解決這個(gè)問(wèn)題。我還添加了 getCart() 方法,它在 DWR 場(chǎng)景中是有用的,但在其他場(chǎng)景中則完全是多余的。由于遠程對象粗粒度 API 的需要以及把某些 Java 類(lèi)型轉化成 JavaScript 的問(wèn)題,所以可以看到遠程 JavaBean 會(huì )被那些只對 Ajax 客戶(hù)有用的方法“污染”。

為了克服這個(gè)問(wèn)題,可以使用包裝器類(lèi)把額外的特定于 DWR 的方法添加到普通 JavaBean。這意味著(zhù) JavaBean 類(lèi)的 Java 客戶(hù)可能看不到與遠程相關(guān)聯(lián)的額外的毛病,而且也允許給遠程方法提供更友好的名稱(chēng) —— 例如用 getPrice() 代替 getFormattedPrice()。圖 4 顯示的 RemoteCart 類(lèi)對 Cart 進(jìn)行了包裝,添加了額外的 DWR 功能:


圖 4. RemoteCart 為遠程功能對 Cart 做了包裝

最后,需要記?。篋WR Ajax 調用是異步的,所以不要期望它們會(huì )按照分派的順序返回。在示例代碼中我忽略了這個(gè)小問(wèn)題,但是在這個(gè)系列的第一篇文章中,我演示了如何為響應加時(shí)間戳,以此作為保證數據到達順序的一種簡(jiǎn)單手段。





回頁(yè)首


結束語(yǔ)

正如所看到的,DWR 提供了許多東西 —— 它允許迅速而簡(jiǎn)單地創(chuàng )建到服務(wù)器端域對象的 Ajax 接口,而不需要編寫(xiě)任何 servlet 代碼、對象序列化代碼或客戶(hù)端 XMLHttpRequest 代碼。使用 DWR 部署到 Web 應用程序極為簡(jiǎn)單,而且 DWR 的安全性特性可以與 J2EE 基于角色的驗證系統集成。但是 DWR 并不是對于任何一種應用程序架構都適合,所以在設計域對象的 API 時(shí)需要做些考慮。

如果想學(xué)習用 DWR 進(jìn)行 Ajax 的利弊的更多內容,最好的方式就是下載并開(kāi)始實(shí)踐。DWR 有許多我沒(méi)有介紹的特性, 文章源代碼 是把 DWR 投入使用的一個(gè)良好起點(diǎn)。請參閱 參考資料,學(xué)習關(guān)于 Ajax、DWR 和相關(guān)技術(shù)的更多內容。

這個(gè)系列中要指出的最重要的一點(diǎn)是:對于 Ajax 應用程序,沒(méi)有包治百病的解決方案。Ajax 是一個(gè)快速發(fā)展的領(lǐng)域,不斷有新技術(shù)涌現。在這個(gè)系列的三篇文章中,我的重點(diǎn)在于帶您開(kāi)始在 Ajax 應用程序的 Web 層中利用 Java 技術(shù) —— 不管是選擇基于 XMLHttpRequest 的帶有對象序列化框架的技術(shù),還是選擇 DWR 這樣的更高級抽象。請在后續幾個(gè)月中留意面向 Java 開(kāi)發(fā)人員介紹 Ajax 的文章。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
面向Java開(kāi)發(fā)人員的Ajax技術(shù)
面向 Java 開(kāi)發(fā)人員的 Ajax: 構建動(dòng)態(tài)的 Java 應用程序
DWR技術(shù)
服務(wù)器推送技術(shù) - ServerPush
AJAX made simple with DWR
Ajax 框架
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久