此驗證框架用于驗證字段。有許多在Web應用程序上進行驗證的方法。這些方法可分為兩類:服務器端方法和客戶端方法。Struts驗證框架是面向基于Java的Web應用環境的最佳框架之一。它能夠配置應用程序,方法是使用服務器端驗證和錯誤消息,此錯誤消息在處理請求時呈現在調用的驗證流程上,它還能夠進行客戶端驗證,方法是使用請求頁面上呈現的JavaScript。
AJAX是一種JavaScript技術,它能夠異步呼叫服務器并獲取XML文檔,這類文檔最近非常流行。其用途之一就是實時數據驗證。
本文關注使用AJAX增強現有struts驗證框架。必須開發幾個組件(例如控制器),以選擇驗證框架,并呈現特定格式的消息(用于客戶端)和標簽庫(處理錯誤消息呈現)。
必要條件需要一個具有Eclipse和Tomcat應用服務器的Windows系統。請確定已在操作系統中注冊了MSXML 3.0 ActiveX對象。還需要Struts庫(http://struts.apache.org)和JDOM庫(www.jdom.org),以用于XML開發(參見圖1和圖2)。


StrustsActionServlet
我們必須擴展來自org.apache.struts.action.ActionServlet的類,以獲得servletMapping變量,此變量存儲關于如何針對動作類將該擴展格式化為瀏覽器地址形式的動作路徑的信息。當添加代碼時,我們必須將web.xml配置為應用服務器的Web應用程序描述符。
web.xml配置如下:
| ... <servlet> <servlet-name>action</servlet-name> <servlet-class>net.sf.struts.servlet.StrutsActionServlet</servlet-class> ... <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> ... StrutsActionServlet Java代碼如下: public class StrutsActionServlet extends the ActionServlet. { public String getServletMapping() { return this.servletMapping; } } |
AjaxValidationRequestProcessor
要在第一步中支持現有Struts框架,我們必須擴展來自Struts軟件包的RequestProcessor。我們必須定制化此請求處理器,因為我們必須判別將如何進行驗證(通過使用現有Struts框架,還是利用AJAX概念),還因為我們將在服務器和客戶端之間制訂一個有關如何解釋消息的契約。在消息呈現方面,我們將使用XML格式,這是一種很好的媒體消息傳遞格式。我們將應用的XML格式的定義是:
XML Format
| XML Format <?xml version="1.0" encoding="UTF-8"?> <message> <identity name=messageAreaId> <description> MessageValue </description> </identity> </message> |
描述
- Identity是客戶端JavaScript用于了解消息將被置于何處的ID。
- Description是在服務器端呈現錯誤消息后的結果。
首先我們需要在繼續流程映射之前,從Web描述符獲得servlet映射配置。調用此流程后,應用程序將準備表單實例,此實例繼承自AjaxForm類。這一處理管理AJAX驗證,并且應進行檢查以確定來自客戶端的請求沒有使用struts驗證框架。其他在請求過程中執行的流程是流程填充(用于收集客戶端發送到動作表單的信息)和流程驗證(通過使用現有Struts驗證框架中已經存在于AjaxValidationRequestProcessor的父類TilesRequestProcessor中的方法)。
來自TilesRequestProcessor的驗證流程將調用所有基于struts驗證框架的驗證,并將動作錯誤存儲到請求。我們需要仔細分析動作錯誤,并生成XML消息驗證,此驗證將被發送到客戶端。因為我們希望更改支持驗證的行為方式,所以驗證流程應檢查所用的驗證框架的指示器(參圖3)。

使用JDOM作為處理引擎,生成XML消息。如圖4所示,如果流程驗證被調用,且驗證框架的條件等同于AJAX驗證框架,則流程將繼續填充錯誤消息并構建XML消息驗證。

該類處理XML消息生成器的功能。此Java類將構建基于identity和description屬性的XML消息。調用方調用了buildXMLMessage之后,它將準備文檔并設置XML消息的根元素。此類還具有一個addNextXMLMessage函數,以將更多驗證消息添加到XML(參見清單1)。
清單1
| ... public void buildXMLMessage() throws ParserConfigurationException { // initiate document builder to prepare the media of XML Message this.rootElement = new Element(CONSTANT_MESSAGE); addNextXMLMessage(); } ... public void addNextXMLMessage() throws ParserConfigurationException { // creating the xml message based on format above Element identityElement = new Element(CONSTANT_IDENTITY); identityElement.setAttribute(CONSTANT_NAME, this.identity); Element descriptionElement = new Element(CONSTANT_DESCRIPTION); descriptionElement.addContent(this.description); identityElement.addContent(descriptionElement); rootElement.addContent(identityElement); } |
此流程方法將響應的內容類型設置為“text/xml”,并將XML消息作為字符串發送。AjaxValidationRequestProcessor代碼上的流程函數如清單2所示。
清單2
| public void process(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { if ( request.getParameter(CONSTANT_VALIDATION_FRAMEWORK_ARG) != null ) { ... this.processValidate(req, resp, form, mapping); response.setContentType(CONSTANT_XML_CONTENT_TYPE); response.getWriter().write(sbXMLMessage.toString()); response.flushBuffer(); } } else { super.process(req, resp); } } |
processValidation方法將填充
動作錯誤,并基于面向客戶端的XML格式契約構建消息。AjaxValidationRequestProcessor代碼上的processValidation函數如下所示:
... ActionErrors errors = (ActionErrors) request.getAttribute(Globals.ERROR_KEY); Locale locale = (Locale) request.getAttribute(Globals.LOCALE_KEY); generateXMLMessage(errors, identity, locale, sbXMLMessage); ... |
客戶端場景構建標簽庫組件
- AjaxJavaScriptLibraryTag:此標簽庫組件在客戶端呈現JavaScript功能,以實現基本XMLHTTP控制器功能。
- AjaxErrorHtmlRenderTag:此標簽庫組件在JSP頁面呈現錯誤消息區域。
開發出標簽庫組件之后,我們需要配置清單3中顯示的標簽庫tld文件。
清單3
| <taglib> <tlibversion>1.0</tlibversion> <jspversion>1.1</jspversion> <shortname>ajaxLib</shortname> <tag> <name>library</name> <tagclass>net.sf.ajax.taglib.AjaxJavaScriptLibrary </tagclass> <bodycontent>JSP</bodycontent> </tag> <tag> <name>error</name> <tagclass>net.sf.ajax.taglib.AjaxErrorHtmlRender </tagclass> <bodycontent>JSP</bodycontent> <attribute> <name>property</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>event</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib> |
構建JSP和Struts配置
要模擬驗證處理的結果,我們首先需要構建呈現層,方法是合并我們已經構建的標簽庫。在此例中,我試圖給出一個示例驗證(通過使用來自Struts的驗證規則組件)以及來自表單本身的驗證。準備五個JSP頁面下的文本框。第一個到第四個文本框使用驗證規則配置,第五個文本框使用來自動作表單的驗證流程。除此之外,我們還需要一個提交按鈕,以在提交表單后模擬它,現有的struts驗證仍在沒有AJAX的情況下工作。用戶界面外觀如圖5所示。

為獲得Struts動作,我們轉到已經構建的JSP。此動作代碼如下所示:
| public ActionForward execute(...) { return mapping.findForward("success"); } |
如果輸入為空,則此動作表單代碼將驗證requiredText屬性。請記住,要從AjaxForm類擴展此表單。動作表單的驗證方法如下所示:
| public ActionErrors validate(...) { ActionErrors errors = new ActionErrors(); if (StringUtils.isEmpty(this.requiredText)) { errors.add("requiredText", new ActionError("error.required.input")); } request.setAttribute(Globals.ERROR_KEY, errors); } |
應用Struts驗證規則
配置Struts驗證規則(例如最小長度、最大長度、電子郵件和模式文本)將應用于客戶端的輸入對象,且配置與清單4類似。
清單4
| <field property="paternText" depends="required,mask"> <arg0 key="label.paternText"/> <var> <var-name>mask</var-name> <var-value>^[0-9]{3}-[0-9]{2}$</var-value> </var> </field> <field property="minLength" depends="minlength"> <arg0 key="label.minLength"/> <arg1 key="${var:minlength}" resource="false"/> <var> <var-name>minlength</var-name> <var-value>5</var-value> </var> </field> <field property="maxLength" depends="maxlength"> <arg0 key="label.maxLength"/> <arg1 key="${var:maxlength}" resource="false"/> <var> <var-name>maxlength</var-name> <var-value>5</var-value> </var> </field> <field property="email" depends="email"> <arg0 key="label.email"/> </field> |
驗證處理流
首先客戶端會初始化XMLHTTP組件以執行到服務器的請求,然后在用戶觸發器開始構建時,URL參數將被發送到服務器。在完成構建參數后,客戶端會連接oneadystatechange XMLHTTP事件,以偵聽來自服務器端的響應。收到響應后,客戶端會開始分析XML驗證消息,并將消息放置到正確的區域(參見圖6)。

如果請求被服務器接受,則服務器會開始檢查AJAX驗證條件的參數,并處理驗證。完成之后,將從生成的錯誤對象過濾出與用戶輸入對象相關的特定錯誤。在過濾流程完成之后,將生成XML消息,并發送回客戶端(參見圖7)。

在本文中,我們構建了一個控制器,它能夠接收來自客戶端的異步請求,并合并struts驗證流程以產生動作錯誤對象。在產生錯誤對象并生成作為應答返回客戶端以指示錯誤消息的XML消息之后,將對被驗證的特定輸入對象進行過濾(參見圖8和圖9)。
