SimpleFramework系列之 - AjaxRequest
一、綜述
AjaxRequest是一個非常重要的組件,在一個基于SimpleFramework的項目中,AjaxRequest被使用的概率幾乎在50%以上,甚至更多。
在開始介紹AjaxRequest之前,我們首先看看HttpServletRequest,下圖介紹一個完整Http請求到響應的生命周期。
一些Web框架(比如:Struts)擴展了Servlet,并通過提供的接口,實現了基于MVC的編程模式,從而取代傳統的Servlet編程。如下圖:
隨著Ajax的流行,基于Ajax的請求變的越來越流行,一般要通過如下幾個步驟來實現:
編寫客戶端代碼(javascript)
編寫請求代碼
通過回調函數處理返回的結果
編寫Servlet處理類
返回結果(可以是html、xml、text或json),等待客戶端回調函數的處理
一些流行的javascript框架,比如Prototype、jQuery等都提供了對Ajax的封裝,您可以很容易的編寫客戶端的請求代碼,這里以Prototype為例:
- new Ajax.Request("/test.action", {
- postBody: "p1=v1&p2=v2",
- encoding: "UTF-8",
- onComplete:function(req) {
- var txt = req.responseText;
- //do data
- }
- );
“/test.action”請求一個Servlet類,并通過業務處理,把需要的數據返回給前端回調函數onComplete。
看似簡單的流程,卻有很多問題需要關注:
實際的項目有上百個甚至更多Ajax請求,那么前端javascript的數量和Servlet的數量就會增長很快。當javascript出現錯誤或更改javascript代碼都會相當麻煩,至于Servlet,您可以通過Struts等技術替代
提交表單需要拼接參數,有沒有更好的辦法?
返回數據的解析。建議在Servlet中直接生成json格式
如果返回數據包含javascript文件(腳本)、CSS文件等,如何動態添加到dom中,如果dom中已經存在這些文件,那又該如何處理
需要對返回數據進行緩存,是否可以處理?
解決以上的問題,你需要付出太多的代價,不過,沒關系,SimpleFramework提供的AjaxRequest組件,讓您用聲明的方式,快速完成Ajax請求。
二、原理
三、實踐
現在就開始我們的AjaxRequest之旅吧!
3.1 組件的聲明
SimpleFramework使用xml文件來描述組件,您可以參考http://simpleframework.net/doc/d2/2.4.1.html獲取更為詳細的信息。
以下是聲明的代碼片段:
- <ajaxRequest name="ajaxTestAction" handleClass="net.simpleframework.demo.TestAction"
- handleMethod="testMethod">
- </ajaxRequest>
在組件聲明中,名稱是必須的,且不能和其它組件名稱重復,因為SimpleFramework通過Filter發現如上的定義,就會自動為客戶端生成 一個$Actions[“ajaxTestAction”]的javascript對象。在客戶端,您就可以通過這個唯一的名稱獲取其javascript對 象的引用。
如果您不了解$Actions,可以通過http://simpleframework.net/doc/d2/2.4.2.html來了解更多內容。
3.2 與HTML頁面元素的事件綁定
HTML頁面元素(比如button)如何綁定到AjaxRequest組件“ajaxTestAction”呢?SimpleFramework采用了最原始的方式,代碼如下:
- <input type="button" value="提交" onclick="$Actions[‘ajaxTestAction’]();" />
很簡單吧,SimpleFramework并沒有改變現有的編程習慣,沒有標簽庫,僅僅是簡單的HTML和Javascript。
3.3 如何提交數據
Ajax可以通過Get或POST來提交數據,但您必須自己拼接參數序列,這個非常麻煩。SimpleFramework提供了一個屬性formSelector,快速提交HTML里您關心的數據區域,參考以下代碼:
- <ajaxRequest name="ajaxTestAction" handleClass="net.simpleframework.demo.TestAction"
- handleMethod="testMethod" formSelector=".div1, .div2 select">
再看一下HTML表單的定義:
- <div class="div1">
- ... ...
- </div>
- <div class="div2">
- ... ...
- </div>
- <input type="button" value="提交" onclick="$Actions[‘ajaxTestAction’]();" />
關于selector,如果您了解Prototype、jQuery等javascript框架,那就一定非常熟悉。如果不了解,建議先在網上Google一下,先了解什么是CSS選擇器。
上述含義是提交類名為“div1”下的所有表單元素和類名為“div2”下的select元素,這是不是比定義一個form標簽要簡單很多呢。
注:如果提交二進制文件,需使用submit組件或swfUpload組件。
3.4 編寫HandleClass
AjaxRequest組件的HandleClass可以理解為Struts的Action,其接口的定義如下:
- package net.simpleframework.web.page.component.base.ajaxrequest;
- public interface IAjaxRequestHandle extends IComponentHandle {
- IForward ajaxProcess(ComponentParameter compParameter) throws Exception;
- }
如果沒有指定handleMethod,則ajaxProcess將會執行,如果指定了handleMethod,則執行名稱為handleMethod的方法,其方法結構和ajaxProcess是一樣的。
建議您繼承AbstractAjaxRequestHandle而不是實現IAjaxRequestHandle,因為抽象父類會提供一些有意義的方法給您使用,對于任何其它組件,這一原則總是適用的。
3.5 IForward介紹
handleClass將會返回IForward接口,類似Struts的ActionForward,但有不同。IForward有三個具體的實現:
TextForward,返回純文本
JsonForward,返回Json格式的文本,構造時需傳遞Map、List、Array等類型
UrlForward,返回HTML,構造時需傳遞url地址
大部分情況,JsonForward是一個更好的選擇。
3.6 編寫回調腳本
定義回調腳本,參考如下代碼:
- <ajaxRequest name="ajaxTestAction" handleClass="net.simpleframework.demo.TestAction"
- handleMethod="testMethod">
- <jsCompleteCallback>
- alert(json);
- alert(responseText);
- </jsCompleteCallback>
- </ajaxRequest>
3.6.1 回調函數原型
在編寫jsCompleteCallback的時候,很多用戶不知道如何下手,更不知道返回的數據在哪。其實,jsCompleteCallback就是一個javascript函數,只不過采用xml描述,把傳遞給你的參數省略了。請看jsCompleteCallback原型的定義:
- jsCompleteCallback = function(req, responseText, json) {
- }
解釋一下三個參數:
req:原生ajax response對象
responseText:返回的文本對象
json:如果handleClass返回的是JsonForward,則json為解析過的JSON對象
3.6.2 通過屬性直接綁定到HTML區域
ajaxRequest很多應用都是返回一段HTML,然后更新到某個區域,如果通過jsCompleteCallback一定會很簡單,下面是一段代碼樣例:
- var div = $("divid");
- div.innerHTML = responseText;
ajaxRequest同時還提供了一個屬性updateContainerId,可以不用寫jsCompleteCallback,而直接綁定到updateContainerId指定的區域id,不光如此,還能執行responseText中的js函數,代碼如下:
- <ajaxRequest name="ajaxTestAction" handleClass="net.simpleframework.demo.TestAction"
- handleMethod="testMethod" updateContainerId="divid">
- </ajaxRequest>
四、高級特性
4.1 動態傳遞參數
如果提交的數據是變化的,或則ajaxRequest組件是一個,但綁定的HTML元素事件是多個,又該怎么處理呢?
舉個實例,比如“發送郵件”,一般分為“保存到草稿”、“直接發送”,因為提交的數據是一樣的,則可以通過動態參數傳遞,在兩個按鈕的事件上分別綁定到同一個ajaxRequest組件。假設ajaxRequest組件的名稱為sentMail,參考如下代碼:
- <input type="button" value="保存到草稿" onclick="$Actions[‘sentMail’]('type=0');" />
- <input type="button" value="直接發送" onclick="$Actions[‘sentMail’]('type=1');" />
$Actions[‘sentMail’]其實就是一個函數,你在調用的時候,可以設置參數為拼接的字符串(見代碼紅色部分),這是一個經常使用的特性。還需要注意一點,參數傳遞的優先級是高于formSelector的。
4.2 自動加載js及css文件
自動加載js及css文件是ajaxRequest組件一個非常重要的特性,您可以直接在Ajax的返回數據中定義js或css文件,而不必擔心它們是否已加載,如何加載等一系列問題。
您可以通過firebug來體驗自動加載過程:)
4.3 作為其它組件的引用
組件的引用是SimpleFramework組件體系一個非常實用的功能。比如,window組件通過引用ajaxRequest組件來裝載window面板內容,代碼如下:
- <ajaxRequest name="ajaxTestPage">
- <urlForward>/window_content.jsp</urlForward>
- </ajaxRequest>
- <window name="testWindow" contentRef="ajaxTestPage" width="480" height="600">
- </window>
當調用了testWindow組件,ajaxTestPage將被觸發并返回/window_content.jsp生成的數據到window面板。以后還會對此特性做更多的介紹。
4.4 緩存返回的數據
ajaxRequest組件的緩存功能非常簡單,設置屬性updateContainerCache=true即可。如果您是注冊用戶,可以在SimpleFramework站點上體驗一下:右上方的個人屬性編輯,采用的是標簽頁,當標簽頁被打開后,下次將使用緩存功能。
4.5 一些不常用的屬性
disabledTriggerAction,當組件被調用時,是否禁止調用元素,默認為true,目的是防止被多次調用,比如用戶連續的點擊操作
parallel,是否允許并行執行,默認為false,在連續調用ajaxRequest時,在允許并行時,才可同時執行,否則將拋棄當前的調用
jobExecute,執行權限,該屬性依賴機構模塊
confirmMessage,客戶端需要確認的消息
throwException(window、alert),異常的展示方式。提供alert展示或window組件展示,window組件展示可獲取更多的異常信息
showLoading,是否顯示裝載進度(右上角顯示),默認為true




















