在寫前幾篇文章的時候,有些朋友建議我的寫一篇關于表單數據校驗的文章。 正如文章的開頭所引用的《Writing Secure Code》的名言:“所有的輸入都是罪惡的”,所以我們應該對所有的外部輸入進行校驗。而表單是應用程序最簡單的入口,對其傳進來的數據,我們必須進行校驗。
其實上篇文章,我本來是打算寫表單數據校驗的內容,但是經過再三思考后,還是決定先寫Struts 2.0轉換器的內容。原因是我認為轉換是校驗的基礎,只有在數據被正確地轉換成其對應的類型后,我們才可以對其取值范圍進行校驗。看個例子相信大家可以更清楚。現在我們就來改造一下《轉換器(Converter)——Struts 2.0中的魔術師》的第一個例子。
首先,從Action開始,修改后的代碼如下:
然后,修改Struts.xml中Action的定義指明輸入地址:
接著,在HelloWorld.jsp中加入錯誤提示:
再修改LocaleConverter.java文件,將內容改為:
之后,修改國際化資源文件,內容為:
發布運行應用程序,在瀏覽器中鍵入http://localhost:8080/Struts2_Validation/HelloWorld.action,在Locale中輸入zh_CN,按“Submit”提交,效果如上篇文章所示。而在服務器控制臺有如下輸出:
上述的輸出說明了Struts 2.0的數據校驗工作方式,它需要經過下面幾個步驟:
不喜歡看文字的朋友,可以參考下面的圖1。
圖1 校驗順序圖
看到這里可能大家會疑問:“這么多地方可以校驗表單數據,到底我應該在那里做呢?”有選擇是好事,但抉擇的過程往往是痛苦的,往往讓人不知所措。如果大家參照以下幾點建議,相信會比較容易地做出正確的抉擇。
在運行上面的例子時,在Locale中輸入zh并提交時出現圖2所示頁面。
圖2 錯誤格式
在Locale中輸入de_DE時,出現如圖3所示頁面。
圖3 取值錯誤
上一節的內容都是關于如何編程實現校驗,這部分工作大都是單調的重復。更多情況下,我們使用Struts 2.0的校驗框架,通過配置實現一些常見的校驗。
我學習編程有個習慣——喜歡先看輸出結果,再看代碼實現。這樣學的好處是先看結果可以刺激學習的激情,也可以在看代碼前自已思考一下如何實現,然后帶著問題去看代碼,那就清晰多了。因此下面我們先來做演示。
首先,在tutorial包下新建ValidationAction.java,代碼如下:
然后,配置上述所建的Ation,代碼片段如下:
接著,創建Input.jsp和Output.jsp,內容分別如下:
再接下來,在tutorial包下創建ValidationAction的校驗配置文件Xxx-validation.xml(Xxx為Action的類名),在本例中該文件名ValidationAction-validation.xml,內容如下:
發布運行應用程序,在地址欄中鍵入http://localhost:8080/Struts2_Validation/Input.jsp,出現如圖4所示頁面。
圖4 Input.jsp
直接點擊“Submit”提交表單,出現圖5所示的頁面。
圖5 錯誤提示
在Required String中隨便填點東西,轉到Output.jsp頁面,如圖6所示。
圖6 Output.jsp
通過上面的例子,大家可以看到使用該校驗框架十分簡單方便。不過,上例還有兩點不足:
當然,要完善以上不足,對于Struts 2.0來說,只是小菜一碟。
下面是具體的實現,首先在國際化資源文件中加入錯誤消息,然后按照上面說明實現。因為要使用Javascript在客戶端顯示出錯信息,所以在加載Input.jsp頁面時,Struts 2.0需要獲得國際化的字符串,故我們需要使用Action來訪問Input.jsp頁面,具體實現請參考《在Struts 2.0中國際化(i18n)您的應用程序》的最后部分。最后發布運行應用程序,直接在頁面中點擊“Submit”,表單沒有被提交并出現錯誤提示,如圖7所示:
圖7 客戶端校驗
校驗框架是通過validation攔截器實現,該攔載被注冊到默認的攔截器鏈中。它在conversionError攔截器之后,在validateXxx()之前被調用。這里又出現了一個選擇的問題:到底是應該在action中通過validateXxx()或validate()實現校驗,還是使用validation攔截器?絕大多數情況,我建議大家使用校驗框架,只有當框架滿足不了您的要求才自已編寫代碼實現。
在上面的例子中,我們通過創建ValidationAction-validation.xml來配置表單校驗。Struts 2.0的校驗框架自動會讀取該文件,但這樣就會引出一個問題——如果我的Action繼承其它的Action類,而這兩個Action類都需要對表單數據進行校驗,那我是否會在子類的配置文件(Xxx-validation.xml)中復制父類的配置嗎?
答案是不,因為Struts 2.0的校驗框架跟《在Struts 2.0中國際化(i18n)您的應用程序》提到的“資源文件查找順序”相似,有特定的配置文件查找順序。不同的是校驗框架按照自上而下的順序在類層次查找配置文件。假設以下條件成立:
如果Dog要被校驗,框架方法會查找下面的配置文件(其中別名是Action在struts.xml中定義的別名):
Struts 2.0已經為您實現很多常用的校驗了,以下在jar的default.xml中的注冊的校驗器。
使用校驗框架既可以方便地實現表單數據校驗,又能夠將校驗與Action分離,故我們應該盡可能使用校驗框架。在使用校驗框架時,請不要忘記通過在資源文件加入invalid.fieldvalue.xxx字符串,顯示適合的類型轉換出錯信息;或者使用conversion校驗器。