入門 08 - ActionError與ActionMessage
<script language=javascript> function toggle(id) { var oldAttachmentVersionsBlock = document.getElementById('attachment' + id); with (oldAttachmentVersionsBlock.style) { if ( display == "none" ) display = "" else display = "none" } var arrowIcon = document.getElementById('arrow' + id); with (arrowIcon) { if (src != null && (src.indexOf('/confluence/images/icons/arrow_closed_active_16.gif') != -1 || src.indexOf('/confluence/images/icons/arrow_closing_active_16.gif') != -1)) { src = '/confluence/images/icons/arrow_opening_active_16.gif'; } else { src = '/confluence/images/icons/arrow_closing_active_16.gif'; } } } </script>
UserForm.java
package onlyfun.caterpillar; import javax.servlet.http.*; import org.apache.struts.action.*; public class UserForm extends ActionForm { protected String name; protected String password; public void setName(String name) { this.name = name; } public void setPassword(String password) { this.password = password; } public String getName() { return name; } public String getPassword() { return password; } public void reset(ActionMapping mapping, HttpServletRequest req) { name = null; password = null; } public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if(getName() == null || getUsername().length() < 1) { errors.add("name",new ActionError("error.name.required")); } if(getPassword() == null || getPassword().length() < 1) { errors.add("password",new ActionError("error.password.required")); } return errors; } } 當使用者發送表單,而表單中有欄位沒有填寫時,則請求中會包括參數名稱,但是值為空字串,如果ActionForm具有某些屬性,而表單並沒有發送對應的參數,則不會設定ActionForm中對應的屬性,這些屬性將為null,我們的validate()中主要在檢查這兩個情況。 validate()方法會傳回ActionErrors物件,ActionErrors可以儲存ActionError的訊息,每一個 ActionError會查詢資源檔中的key-value對應,當validate()丟回ActionErrors物件時, ActionServlet就不會繼續進行接下來的工作,而是導回structs-config.xml所設定的位置,例如:
struts-config.xml
<global-forwards> <forward name="welcome" path="/Welcome.do"/> </global-forwards> <form-beans> <form-bean name="userForm" type="onlyfun.caterpillar.UserForm"/> </form-beans> <action-mappings> <action path="/Welcome" type="org.apache.struts.actions.ForwardAction" parameter="/pages/Welcome.jsp"/> <action path="/LoginAction" type="onlyfun.caterpillar.LoginAction" name="userForm" validate="true" input="/pages/Welcome.jsp"> <forward name="greeting" path="/pages/greeting.jsp"/> </action> </action-mappings> 為了要能使用validate()方法,<action>中的validate屬性必須設定為true,而input屬性也是必要的,當validate()傳回ActionErrors時,就會forward至input屬性所設定的位置,ActionErrors中的訊息,我們可以使用<html:errors/>標籤來顯示,待會就會看到。 ActionForm中驗證了屬性為null及空字串的可能,這是資料完整性的驗證,接下來我們要驗證資料的正確性,是否符合我們所設定的名稱與密碼,我們改寫前一個主題的LoginAction,看看寫法有何不同:
LoginAction.java
package onlyfun.caterpillar; import javax.servlet.http.*; import org.apache.struts.action.*; import org.apache.commons.beanutils.*; public class LoginAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String name = (String) PropertyUtils.getSimpleProperty(form, "name"); String password = (String) PropertyUtils.getSimpleProperty(form, "password"); if(!(name.equals("caterpillar") && password.equals("1234"))) { ActionMessages messages = new ActionMessages(); messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("message.namepass.notmatched")); saveMessages(request, messages); return mapping.findForward("welcome"); } else { request.getSession().setAttribute("valid_user", form); return mapping.findForward("greeting"); } } } 在這次的程式中,我們使用了org.apache.commons.beanutils中的PropertyUtils類別來協助我們取 ActionForm中的值,好處是不用理會ActionForm真正的形態,PropertyUtils會自動幫我們判斷, getSimpleProperty()傳回的是Object,我們將之轉換為String。 ActionMessages是Struts 1.1所新增的類別,它變成了ActionErrors的父類別,同樣的,ActionMessage也是Struts 1.1新增的類別,它是ActionError的父類別,資料的格式與完整性檢查在ActionForm中我們已經驗證了,接下來我們在Action中檢查是否符合名稱與密碼,如果不符合就加入相關的訊息。 在Struts 1.1中特意將Message與Error區別,該是認定所謂的Error是使用者的輸入在完整性或格式等上有誤,而Message是指輸入的資料基本上沒有錯誤,但不能符合後續的商務處理。 為了要能夠顯示錯誤與訊息,我們必須在application_zh.properties中加入key-value對應,如下:
application_zh.properties
# -- error -- error.name.required=沒有輸入名稱 error.password.required=沒有輸入密碼 #-- message -- message.namepass.notmatched=名稱與密碼不正確 為了要能使用中文,記得使用native2ascii工具程式進行轉換,接下來我們來看看我們的Welcome.jsp如何撰寫,要注意的是在<html:errors/>與<htm:messages/>的使用:
Welcome.jsp
<%@ taglib uri="/tags/struts-bean" prefix="bean" %> <%@ taglib uri="/tags/struts-html" prefix="html" %> <%@page contentType="text/html; charset=Big5"%> <html:html locale="true"> <head> <title><bean:message key="welcome.title"/></title> <html:base/> </head> <body bgcolor="white"> <html:errors/> <html:messages id="messages" message="true"> <bean:write name="messages"/> </html:messages> <h3>請登入</h3> <html:form action="/Login"> 名稱:<html:text property="name" size="20"/><br> 密碼:<html:password property="password" size="20"/><br> <html:submit/> <html:reset/> </html:form> </body> </html:html> 如果由於ActionForm傳回ActionErrors物件而返回Welcome.jsp,則<html:errors/>標籤會顯示ActionErrors中的相關錯誤訊息,我們利用<html:messages/>來檢查返回中是否也包括 ActionMessages物件,如果有的話就取出並使用<bean:write/>標籤顯示之。 下面是執行時未填寫欄位所顯示的錯誤訊息的一個例子: <html lang="zh"> <head> <title>哈囉!Struts!</title> <base href="http://localhost:8080/HelloStruts/pages/Welcome.jsp"> </head> <body bgcolor="white"> <UL> <LI>沒有輸入名稱 </LI><LI>沒有輸入密碼 </LI></UL> <h3>請登入</h3> <form name="UserForm" method="post" action="/HelloStruts/Login.do"> 名稱:<input type="text" name="name" size="20" value=""><br> 密碼:<input type="password" name="password" size="20" value=""><br> <input type="submit" value="Submit"> <input type="reset" value="Reset"> </form> </body> </html> 注意到ActionErrors在Struts 1.2之後可能會被標示為deprecated,將來可能會改以ActionMessages取代,所以<html:errors/>在將來必須以下面的方式來取代: <html:messages id="msg" > <bean:write name="msg"/> </html:messages> 在之前的例子中,在<html:messages/>的屬性上設定message為true,這表示顯示ActionMessages的內容:代碼: <html:messages id="messages" message="true"> <bean:write name="messages"/> </html:messages>
|