很久沒有更新BLOG了,前一段時間公司的項目比較忙,另外我還和一位出版社的朋友談寫書的事情,所以一直沒有時間,完成《Struts 2與AJAX》。后來寫書的事情吹了,趁今天有點空閑就把它完成。
在大家看這部分文章之前,我想對于寫書的事情說兩句,或者應該叫發牢騷才對。通過這次寫書失敗的經歷,我明白為什么國內的IT書籍多數是濫于充數、粗制濫造、缺乏經典。其實說白了就是一個“錢”字作怪。為了市場,很多編輯可能會“建議”你去“抄考”一些國內相對暢銷的同類書籍,例如寫Struts就一定要按所謂的MVC進行目錄分類,美其名曰“容易入門”。我認為“MVC”的概念雖然重要,但對初學者而言,需要對編程有一定的了解才容易明白此概念。另外,為了“實用”,不惜使用相同的技術重復編寫不同的范例。可能是我不太了解讀者的心理吧。
言歸正傳,在上兩部分的《Struts 2與AJAX》中我介紹了Struts 2與DOJO結合實現AJAX的知識,本文將介紹在Struts 2中使用DWR實現AJAX表單校驗。
DWR(Direct Web Remoting)是在Java EE中較流行的AJAX框架,它的最大優勢就是可以像使用本地的Javascript函數一樣,調用服務器上的Java方法。如下圖所示:
圖1 DWR工作原理
其實DWR原理也不復雜,它先在web.xml中配置一個Servlet,映射到特定的路徑(通常是%CONTEXT_PATH%/dwr/*)。這個Servlet的作用就是初始化要暴露給Javascript調用的Java類(通過dwr.xml進行配置),并生成相應的代理的Javascript類代碼。在XHR請求到來的時候,Servlet負責將請求的參數變成對應的Java對象,并以其為參數調用目標Java方法,并將返回值轉化為Javascript代碼。詳情請參考:http://getahead.ltd.uk/dwr/
在Struts 2.0.x中使用DWR實現AJAX表單校驗。在大家掌握了DWR的原理后,下面我想詳細介紹一下實現的步驟。
首先,到以下站點https://dwr.dev.java.net/files/documents/2427/47455/dwr.jar下載DWR的1.1.4版本的JAR包。需要注意的是,DWR雖然已經發布2.0版本,但它與1.1.4有很大的區別,所以請大家不要使用2.0版本,否則會出現異常的;
接著,新建WEB工程,將下圖所示的JAR包加入到工程的“Build Path”中;
圖2 依賴的JAR包
接下來,配置web.xml文件,內容如下:
然后是DWR的配置文件:
通過以上配置,我們可以將DWRValidator中的方法暴露為Javascript可以調用的遠程接口。
在正確完成以上步驟之后,我們發布運行一下應用程序,在瀏覽器地址欄中輸入http://localhost:8080/Struts2_Ajax3/dwr/,應該會出現如下頁面:
圖3 DWR Servlet默認輸出頁面
接下來,我們要開始編寫Action類了,代碼如下:
上述代碼一目了然,相信大家已經很熟悉了。下面,我們再來看看表單校驗的配置代碼:
對于AjaxValidation類的name、password和age三個字段,我分別用了非空、正規表達式和范圍驗證。正規表達式(?!^[0-9]*$)(?!^[a-zA-Z]*$)^([a-zA-Z0-9]{8,10})$的作用是保證密碼由至少包括一個數字和一個字母,且不能含有符號的長度為8到10的字符串組成。它也是所謂強密碼(Strong Password)的普通實現。
接下來的是JSP的代碼,內容如下:
以上代碼也不復雜,不過需要的是注意的是除了要加入<s:head theme="ajax" />外,<s:form />也必須加入validate="true" theme="ajax"的屬性。
最后是Struts 2的配置文件,內容如下所示:
最后發布運應用程序,在瀏覽器地址欄中輸入http://localhost:8080/Struts2_Ajax3/AjaxValidation!input.action出現如下圖所示頁面:
圖4 AjaxValidation頁面輸出
在文本框中輸入錯誤的值使頁面出現錯誤提示信息,如下圖所示:
圖5 AjaxValidation頁面錯誤提示
可能有朋友會問怎么知道這是通過AJAX進行校驗的呢?在這里我向大家推薦一個AJAX開發必備的工具——Firebug。Firebug是Firefox的一個功能強大的插件,它可以準確地輸出和定位Javascript的錯誤、通過直觀的方式查看HTML文檔的DOM及其樣式、所見即所得的編輯方式,更值得一贊的是它可以方便地對Javascript進行跟蹤和調試,如果你希望這進一步了解這個工具,請安裝Firefox 2.0以上版本,并使用它瀏覽以下網址http://www.getfirebug.com。
在安裝完成Firebug之后,在Firefox中打開http://localhost:8080/Struts2_Ajax3/AjaxValidation!input.action,按“F12”鍵找開Firebug窗口,如果你第一次使用Firebug,請點擊其窗口中的鏈接“Enable Firebug”激活插件。之后,點擊“Net”,并在出現的菜單中點擊選中“XHR”。然后將光標移入文本框,再將光標移出使文本框失去焦點,你可以看到Firebug窗口會多出一項記錄,如下圖所示:
圖6 Firebug中查看XHR請求
這就證明你在文本框失去焦出時,Struts 2會發送XHR請求到服務器以對該文本框值進行校驗。有興趣的朋友可以通過Firebug,研究XHR的請求與響應,這樣可以加深對DWR工作原理的理解。
雖然在Struts 2實現AJAX表單校驗是一件非常簡單的事,但我建議大家不要在所有的場合都使用這個功能,原因可以分為以下幾個方面:
讀到這里,有的朋友可能會問:“那么什么時候才應該使用AJAX表單校驗呢?”答案其實很簡單,當我們的校驗在頁面加載時還不能夠確定的情況下,就應該使用這個功能。例如,注冊用戶時,校驗用戶名是否已經存在;或者校驗涉及過多的頁務邏輯等。
現在讓我們來改造一下上述例子,對于name我們可以使用AJAX校驗,但對于其它的字段應該使用純Javascript的校驗。
在tutorial.AjaxValidation類加入如下方法:
用于模擬用戶注冊的場境,當然在真實情況應該在數據庫中檢查用戶是否存在。
接下來再修改JSP文件,將<s:form />里面的內容改為如下所示代碼:
對比早前的JSP代碼,大家可以看出我將<s:form />的theme改成了“ajax_xhtml”,這個theme不是Struts 2自帶,需要自定義。另外,除了Name使用了ajax的theme之外,其它的表單標簽的theme都為xhtml,如此一來便可以實現只有當Name文本框失去焦點時才發生AJAX表單校驗。
接下來,應該是我們的自定義ajax_xhtml的theme了。在源代碼文件夾下新建包“template.ajax_xhtml”,然后在其中加入form.ftl和form-close.ftl文件,內容分別如下:
上述的文件與xhtml theme中的form.ftl文件相似,我只是加入了AJAX表單校驗所用的Javascript庫,以便theme為ajax的表單標簽使用。
這個文件與xhtml theme中的form-close.ftl文件相同。
最后發布運行應用程序,大家可以發現在Password與Age的校驗,只有在表單提交時才發生,而且是純Javascript的校驗。不過,以上代碼還不是很完善,在行為上有些BUG。
Struts 2相比一些其它的框架,在實現AJAX方面的確簡單很多。更激動人心的是Struts 2的標簽庫支持基于模板的輸出,使得開發者可以跟據自身的需要方便地改變標簽的行為。
在將要發布的Struts 2.1版本中,AJAX表單校驗將不再使用DWR,統一使用DOJO實現,詳情請參考:http://struts.apache.org/2.0.9/docs/ajax-validation.html。