通過繼承ActionSupport類來完成Action開發,ActionSupport類不僅對Action接口進行簡單實現, 同時增加了驗證、本地化等支持。真實開發中自定義Action都需要繼承該類。對用戶登錄添加表單驗證功能
ActionSupport類的作用:
struts2不要求我們自己設計的action類繼承任何的struts基類或struts接口,但是我們為了方便實現我們自己的action,大多數情況下都會繼承com.opensymphony.xwork2.ActionSupport類,並重寫此類裡的public String execute() throws Exception方法。因為此類中實現了很多的實用藉口,提供了很多默認方法,這些默認方法包括國際化信息的方法、默認的處理用戶請求的方法等,這樣可以大大的簡化Acion的開發。 Struts2中通常直接使用Action來封裝HTTP請求參數,因此,Action類裡還應該包含與請求參數對應的屬性,並且為屬性提供對應的getter和setter方法。
那麼Action 接口和ActionSupport類的區別是什麼呢?
Action接口有:
public static final String SUCCESS = "success";public static final String NONE = "none";public static final String ERROR = "error";public static final String LOGIN = "login";public String execute() throws Exception;
可以看到有五個靜態常量和返回類型為String 的execute()
而Actionsupport這個工具類在實現了Action接口的基礎上還定義了一個validate()方法,重寫該方法,它會在execute()方法之前執行,如校驗失敗,會轉入input處,必須在配置該Action時配置input屬性。
另外,Actionsupport還提供了一個getText(String key)方法還實現國際化,該方法從資源文件上獲取國際化信息.
這樣在自定義標籤時可以定義一個變量為new actionsupport對象實現國際化。
Actionsupport類有(源碼):
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {protected static Logger LOG = LoggerFactory.getLogger(ActionSupport.class);private final ValidationAwareSupport validationAware = new ValidationAwareSupport();private transient TextProvider textProvider;private Container container;public void setActionErrors(Collection<String> errorMessages) {validationAware.setActionErrors(errorMessages);}public Collection<String> getActionErrors() {return validationAware.getActionErrors();}public void setActionMessages(Collection<String> messages) {validationAware.setActionMessages(messages);}public Collection<String> getActionMessages() {return validationAware.getActionMessages();}@Deprecatedpublic Collection<String> getErrorMessages() {return getActionErrors();}@Deprecatedpublic Map<String, List<String>> getErrors() {return getFieldErrors();}public void setFieldErrors(Map<String, List<String>> errorMap) {validationAware.setFieldErrors(errorMap);}public Map<String, List<String>> getFieldErrors() {return validationAware.getFieldErrors();}public Locale getLocale() {ActionContext ctx = ActionContext.getContext();if (ctx != null) {return ctx.getLocale();} else {if (LOG.isDebugEnabled()) {LOG.debug("Action context not initialized");}return null;}}public boolean hasKey(String key) {return getTextProvider().hasKey(key);}public String getText(String aTextName) {return getTextProvider().getText(aTextName);}public String getText(String aTextName, String defaultValue) {return getTextProvider().getText(aTextName, defaultValue);}public String getText(String aTextName, String defaultValue, String obj) {return getTextProvider().getText(aTextName, defaultValue, obj);}public String getText(String aTextName, List<?> args) {return getTextProvider().getText(aTextName, args);}public String getText(String key, String[] args) {return getTextProvider().getText(key, args);}public String getText(String aTextName, String defaultValue, List<?> args) {return getTextProvider().getText(aTextName, defaultValue, args);}public String getText(String key, String defaultValue, String[] args) {return getTextProvider().getText(key, defaultValue, args);}public String getText(String key, String defaultValue, List<?> args, ValueStack stack) {return getTextProvider().getText(key, defaultValue, args, stack);}public String getText(String key, String defaultValue, String[] args, ValueStack stack) {return getTextProvider().getText(key, defaultValue, args, stack);}public String getFormatted(String key, String expr) {Map<String, Object> conversionErrors = ActionContext.getContext().getConversionErrors();if (conversionErrors.containsKey(expr)) {String[] vals = (String[]) conversionErrors.get(expr);return vals[0];} else {final ValueStack valueStack = ActionContext.getContext().getValueStack();final Object val = valueStack.findValue(expr);return getText(key, Arrays.asList(val));}}public ResourceBundle getTexts() {return getTextProvider().getTexts();}public ResourceBundle getTexts(String aBundleName) {return getTextProvider().getTexts(aBundleName);}public void addActionError(String anErrorMessage) {validationAware.addActionError(anErrorMessage);}public void addActionMessage(String aMessage) {validationAware.addActionMessage(aMessage);}public void addFieldError(String fieldName, String errorMessage) {validationAware.addFieldError(fieldName, errorMessage);}public String input() throws Exception {return INPUT;}public String doDefault() throws Exception {return SUCCESS;}public String execute() throws Exception {return SUCCESS;}public boolean hasActionErrors() {return validationAware.hasActionErrors();}public boolean hasActionMessages() {return validationAware.hasActionMessages();}public boolean hasErrors() {return validationAware.hasErrors();}public boolean hasFieldErrors() {return validationAware.hasFieldErrors();}public void clearFieldErrors() {validationAware.clearFieldErrors();}public void clearActionErrors() {validationAware.clearActionErrors();}public void clearMessages() {validationAware.clearMessages();}public void clearErrors() {validationAware.clearErrors();}public void clearErrorsAndMessages() {validationAware.clearErrorsAndMessages();}public void validate() {}@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}public void pause(String result) {}private TextProvider getTextProvider() {if (textProvider == null) {TextProviderFactory tpf = new TextProviderFactory();if (container != null) {container.inject(tpf);}textProvider = tpf.createInstance(getClass(), this);}return textProvider;}@Injectpublic void setContainer(Container container) {this.container = container;}可以看到裡面有很多的方法,但我們很明顯看到有一個我們很了解的,validate(),數據校驗的方法。通過這個方法,我們可以登錄時,用戶名和密碼為空的提示,或其他・・
現在舉一個簡單的例子:當用戶名和密碼為空,給客戶一個友好提示。
下面通過兩種方式來闡述Struts 2的數據校驗功能。
1. 編碼方式校驗
1) Action一定要繼承自ActionSupport
2) 針對某個要進行校驗的請求處理方法編寫一個public void validateXxx()方法,在方法內部進行表單數據校驗.
3) 也可針對所有的請求處理方法編寫public void validate()方法。
4) 在校驗方法中,可以通過addFieldError()方法來添加字段校驗錯誤消息。
5) 當校驗失敗時,Struts框架會自動跳轉到name為input的Result頁面。在校驗失敗頁面中,可以使用<s:fielderror/>來顯示錯誤消息
6) 簡單,靈活。但重用性不高
重寫validate方法
1.我們編寫的Action一般繼承與ActionSupport,而ActionSupport不僅實現了Action接口,還實現了Validatable接口,提供了數據校驗功能。在Validatable接口中定義一個validate方法,重寫該方法,如果校驗表單輸入域出現錯誤,則將錯誤添加到ActionSupport類的fieldError域中,然後通過OGNL表達式輸出。
下面是用戶登錄校驗界面:
<body><%--輸出校驗信息--%><%--想要單個提示<s:fielderror fieldName="uname"/>--%><%--<s:property value=""/>--%><div style="color:red"><s:fielderror/></div> <s:form name="form1" namespace="/" method="post" action="LoginValidateAction"><s:div>請輸入用戶名:<s:textfield name="user.uname" ></s:textfield></s:div><s:div>請輸入密碼:<s:password name="user.upwd" ></s:password></s:div><s:submit value="登錄"></s:submit></s:form><%--debug --%><s:debug></s:debug></body>
用戶輸入數據後,提交到LoginValidateAction 中:
public class LoginValidateAction extends ActionSupport implements Action {public User user;public Map<String, Object> map;//驗證的方法,會對所有的Action起作用@Override public void validate() {if(user.getUname().length()==0){addFieldError("uname", "用戶名不能為空!");}if(user.getUpwd().length()==0){addFieldError("upwd", "密碼不能為空!");} } //處理業務的方法public String execute() throws Exception {System.out.println(user.getUname());if(user.getUname().equals("admin")&&user.getUpwd().equals("admin")){//讓Struts2注入map集合map.put("uname", user.getUname());//如果登錄成功,返回“ success”return SUCCESS;}else{//登錄失敗,返回errorreturn INPUT; //此處一定是input}}/*** @return the user*/public User getUser() {return user;}/*** @param user the user to set*/public void setUser(User user) {this.user = user;}上面的LoginValidateAction類重寫了validate方法,該方法會在執行excute方法之前執行,如果執行該方法之後,Action類的filedError中包含了數據校驗錯誤,請求將被轉發到input邏輯視圖。
struts.xml配置如下:
<!-- 數據校驗--><action name="LoginValidateAction"><!-- 結果為“success”時,跳轉至success.jsp頁面--><result name="success">success.jsp</result><!-- 結果為"error"時,跳轉至fail.jsp頁面或還在登錄界面login.jsp--><result name="input">LoginValidateAction.jsp</result><result name="login">fail.jsp</result> <result name="error">fail.jsp</result> </action>
在客戶端的效果:
但是大家注意沒有呢,當提示錯誤的時候不太是我們想要的的效果顯示。
這個不是我們所想要的,那麼我們怎麼改呢?其實這主要顯示的struts2主題樣式導致的,
再來看看:
它自動給我們添加了樣式。 struts2提供了三種主題,ajax, simple, xhtml,它默認的是xhtml主題,當然你可以寫任意個你自己的主題,我們稱之為自定義主題。可以通過設置解決以上問題
有兩種方法可以解決:
1.簡單的方法(也很實用,針對所有struts2標籤),在Struts.xml中,加上下一行代碼就可以了。
<constant name="struts.ui.theme" value="simple" />
代表所有的頁面採用的都是simple主題了,這時它輸出的頁面,不回添加任何多餘的代碼,比如table tr td 等,我們就可以像其他編輯頁面的方式編輯頁面的風格。
現在再來看看,錯誤的提示格式
我們可以通過設置這樣一個標籤:
<s:property value="errors.uname[0]"/>
把這個標籤註釋掉:
<div style="color:red"><s:fielderror/></div>
但我們設置成這樣時,會出現這樣的效果。
這種效果就有點想我們平常輸入錯誤時的那個提示了,還有其他屬性值,這裡就不用一一列舉了。
使用Struts2的校驗框架
XML配置方式校驗。
在編碼方式之前被執行。
1) 針對要校驗的Action類,在同包下編寫一個名為:Action類名-validation.xml校驗規則文件。
2) 在校驗規則文件中添加校驗規則:具體的校驗器名,參數可參看Struts2的reference或Struts2的API。
a) Field校驗:針對Action類中每個非自定義類型的Field進行校驗的規則。
<field name="要校驗的Field名"><field-validator type="校驗規則器名" short-circuit="是否要短路徑校驗(默認是false)"><param name="校驗器要使用的參數名">值</param><message>校驗失敗時的提示消息</message></field-validator><!-- 還可添加其它的校驗規則--></field>
b) 非Field校驗:針對Action類的某些Field使用OGNL表達進行組合校驗。
<validator type="fieldexpression"><param name="fieldName">pwd</param><param name="fieldName">pwd2</param><param name="expression"><![CDATA[pwd==pwd2]]></param><!-- OGNL表達式--><message>確認密碼和密碼輸入不一致</message></validator>
c) visitor校驗:主要是用來校驗Action類中的自定義類型Field。 (針對使用模型驅動方式時)
i) 在Action類的的校驗規則文件中針對自定義類型Field使用visitor校驗規則。
<!-- 針對自定義Field使用visitor校驗--><field name="user"><field-validator type="required" short-circuit="true"><message>用戶的信息必填</message><!-- 消息前綴--></field-validator><field-validator type="visitor"><!-- 指定為visitor校驗規則--><param name="context">userContext</param><!-- 指定本visitor校驗的上下文名--><param name="appendPrefix">true</param><!-- 是否要添加校驗失敗消息的前綴--><message>用戶的</message><!-- 消息前綴--></field-validator></field>
ii) 針對visitor的Field編寫一個校驗規則文件.文件名為: visitor字段類型名[-visitor校驗的上下文名]-validation.xml. 例如: 本例中的文件名為User-userContext-validation.xml
注意: 此文件要存放到visitor字段類型所在的包下.
iii) 在visitor的Field校驗規則文件中針對要校驗的Field添加校驗規則.
我們還可以不重寫validate方法,而通過增加校驗配置文件來進行數據校驗。這個校驗配置文件通過使用Struts2已有的校驗器來完成對錶單域的校驗,下面以requiredstring校驗器為例,這個校驗器是一個必填校驗器,指定某個表單域必須輸入。
下面是這個校驗配置文件LoginValidateAction-validation.xml的寫法:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"><validators><field name="uname"><field-validator type="requiredstring"><message>用戶名不能為空</message></field-validator></field><field name="upwd"><field-validator type="requiredstring"><message>密碼不能為空</message></field-validator><field-validator type="stringlength"><param name="maxLength">18</param><param name="minLength">6</param><message>密碼長度應該在${minLength}--${maxLength}位之間</message></field-validator></field></validators>注意:這個校驗配置文件必須遵守下面兩個規則:
1、該文件命運格式必須是Action類名-validation.xml,例如本例中該文件名為:LoginValidateAction-validation.xml
2、該文件必須與Action類的class文件位於同一路徑下,本例中文件位於
LoginValidateAction類的代碼還是一樣:
public class LoginValidateAction extends ActionSupport implements Action {public User user;public Map<String, Object> map;//驗證的方法,會對所有的Action起作用@Override public void validate() {if(user.getUname().length()==0){addFieldError("uname", "用戶名不能為空!");}if(user.getUpwd().length()==0){addFieldError("upwd", "密碼不能為空!");} } //處理業務的方法public String execute() throws Exception {System.out.println(user.getUname());if(user.getUname().equals("admin")&&user.getUpwd().equals("admin")){//讓Struts2注入map集合map.put("uname", user.getUname());//如果登錄成功,返回“ success”return SUCCESS;}else{//登錄失敗,返回errorreturn INPUT; //此處一定是input}}/*** @return the user*/public User getUser() {return user;}/*** @param user the user to set*/public void setUser(User user) {this.user = user;}以上所述是小編給大家介紹的Struts 2 數據校驗功能及校驗問題的解決方案,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!