Struts 2 數(shù)據(jù)校驗(yàn)功能及校驗(yàn)問題的解決方案
通過繼承ActionSupport類來完成Action開發(fā),ActionSupport類不僅對(duì)Action接口進(jìn)行簡(jiǎn)單實(shí)現(xiàn), 同時(shí)增加了驗(yàn)證、本地化等支持 。真實(shí)開發(fā)中自定義Action都需要繼承該類。對(duì)用戶登錄添加表單驗(yàn)證功能
ActionSupport類的作用:
struts2不要求我們自己設(shè)計(jì)的action類繼承任何的struts基類或struts接口,但是我們?yōu)榱朔奖銓?shí)現(xiàn)我們自己的action,大多數(shù)情況下都會(huì)繼承com.opensymphony.xwork2.ActionSupport類,并重寫此類里的public String execute() throws Exception方法。因?yàn)榇祟愔袑?shí)現(xiàn)了很多的實(shí)用借口,提供了很多默認(rèn)方法,這些默認(rèn)方法包括國(guó)際化信息的方法、默認(rèn)的處理用戶請(qǐng)求的方法等,這樣可以大大的簡(jiǎn)化Acion的開發(fā)。 Struts2中通常直接使用Action來封裝HTTP請(qǐng)求參數(shù),因此,Action類里還應(yīng)該包含與請(qǐng)求參數(shù)對(duì)應(yīng)的屬性,并且為屬性提供對(duì)應(yīng)的getter和setter方法。
那么Action 接口和 ActionSupport類的區(qū)別是什么呢?
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;
可以看到有五個(gè)靜態(tài)常量和返回類型為String 的execute()
而Actionsupport這個(gè)工具類在實(shí)現(xiàn)了Action接口的基礎(chǔ)上還定義了一個(gè)validate()方法,重寫該方法,它會(huì)在execute()方法之前執(zhí)行,如校驗(yàn)失敗,會(huì)轉(zhuǎn)入input處,必須在配置該Action時(shí)配置input屬性。
另外,Actionsupport還提供了一個(gè)getText(String key)方法還實(shí)現(xiàn)國(guó)際化,該方法從資源文件上獲取國(guó)際化信息.
這樣在自定義標(biāo)簽時(shí)可以定義一個(gè)變量為new actionsupport對(duì)象實(shí)現(xiàn)國(guó)際化。
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(); } @Deprecated public Collection<String> getErrorMessages() { return getActionErrors(); } @Deprecated public 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() { } @Override public 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; } @Inject public void setContainer(Container container) { this.container = container; }
可以看到里面有很多的方法,但我們很明顯看到有一個(gè)我們很了解的,validate(),數(shù)據(jù)校驗(yàn)的方法。通過這個(gè)方法,我們可以登錄時(shí),用戶名和密碼為空的提示,或其他··
現(xiàn)在舉一個(gè)簡(jiǎn)單的例子:當(dāng)用戶名和密碼為空,給客戶一個(gè)友好提示。
下面通過兩種方式來闡述Struts 2的數(shù)據(jù)校驗(yàn)功能。
1. 編碼方式校驗(yàn)
1) Action一定要繼承自ActionSupport
2) 針對(duì)某個(gè)要進(jìn)行校驗(yàn)的請(qǐng)求處理方法編寫一個(gè) public void validateXxx()方法,在方法內(nèi)部進(jìn)行表單數(shù)據(jù)校驗(yàn).
3) 也可針對(duì)所有的請(qǐng)求處理方法編寫public void validate()方法。
4) 在校驗(yàn)方法中,可以通過addFieldError()方法來添加字段校驗(yàn)錯(cuò)誤消息。
5) 當(dāng)校驗(yàn)失敗時(shí),Struts框架會(huì)自動(dòng)跳轉(zhuǎn)到name為input的Result頁(yè)面。在校驗(yàn)失敗頁(yè)面中,可以使用<s:fielderror/>來顯示錯(cuò)誤消息
6) 簡(jiǎn)單,靈活。但重用性不高
重寫validate方法
1.我們編寫的Action一般繼承與ActionSupport,而ActionSupport不僅實(shí)現(xiàn)了Action接口,還實(shí)現(xiàn)了Validatable接口,提供了數(shù)據(jù)校驗(yàn)功能。在Validatable接口中定義一個(gè)validate方法,重寫該方法,如果校驗(yàn)表單輸入域出現(xiàn)錯(cuò)誤,則將錯(cuò)誤添加到ActionSupport類的fieldError域中,然后通過OGNL表達(dá)式輸出。
下面是用戶登錄校驗(yàn)界面:
<body> <%--輸出校驗(yàn)信息--%> <%--想要單個(gè)提示 <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>請(qǐng)輸入用戶名:<s:textfield name="user.uname" ></s:textfield></s:div> <s:div>請(qǐng)輸入密碼:<s:password name="user.upwd" ></s:password></s:div> <s:submit value="登錄"></s:submit> </s:form> <%--debug --%> <s:debug></s:debug> </body>
用戶輸入數(shù)據(jù)后,提交到LoginValidateAction 中:
public class LoginValidateAction extends ActionSupport implements Action { public User user; public Map<String, Object> map; //驗(yàn)證的方法,會(huì)對(duì)所有的Action起作用 @Override public void validate() { if(user.getUname().length()==0){ addFieldError("uname", "用戶名不能為空!"); } if(user.getUpwd().length()==0){ addFieldError("upwd", "密碼不能為空!"); } } //處理業(yè)務(wù)的方法 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{ //登錄失敗,返回 error return 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方法,該方法會(huì)在執(zhí)行excute方法之前執(zhí)行,如果執(zhí)行該方法之后,Action類的filedError中包含了數(shù)據(jù)校驗(yàn)錯(cuò)誤,請(qǐng)求將被轉(zhuǎn)發(fā)到input邏輯視圖。
struts.xml配置如下:
<!-- 數(shù)據(jù)校驗(yàn) --> <action name="LoginValidateAction" class="cn.struts2.action.LoginValidateAction"> <!-- 結(jié)果為“success”時(shí),跳轉(zhuǎn)至success.jsp頁(yè)面 --> <result name="success">success.jsp</result> <!-- 結(jié)果為"error"時(shí),跳轉(zhuǎn)至fail.jsp頁(yè)面 或 還在登錄界面 login.jsp--> <result name="input">LoginValidateAction.jsp</result> <result name="login">fail.jsp</result> <result name="error">fail.jsp</result> </action>
在客戶端的效果:
但是大家注意沒有呢,當(dāng)提示錯(cuò)誤的時(shí)候不太是我們想要的的效果顯示。
這個(gè)不是我們所想要的,那么我們?cè)趺锤哪兀科鋵?shí)這主要顯示的struts2主題樣式導(dǎo)致的,
再來看看:
它自動(dòng)給我們添加了樣式。struts2提供了三種主題,ajax, simple, xhtml,它默認(rèn)的是xhtml主題,當(dāng)然你可以寫任意個(gè)你自己的主題,我們稱之為自定義主題??梢酝ㄟ^設(shè)置解決以上問題
有兩種方法可以解決:
1.簡(jiǎn)單的方法(也很實(shí)用,針對(duì)所有struts2標(biāo)簽),在Struts.xml中,加上下一行代碼就可以了。
<constant name="struts.ui.theme" value="simple" />
代表所有的頁(yè)面采用的都是 simple主題了,這時(shí)它輸出的頁(yè)面,不回添加任何多余的代碼,比如 table tr td 等,我們就可以像其他編輯頁(yè)面的方式編輯頁(yè)面的風(fēng)格。
現(xiàn)在再來看看,錯(cuò)誤的提示格式
我們可以通過設(shè)置這樣一個(gè)標(biāo)簽:
<s:property value="errors.uname[0]"/>
把這個(gè)標(biāo)簽注釋掉:
<div style="color:red"><s:fielderror/></div>
但我們?cè)O(shè)置成 這樣時(shí),會(huì)出現(xiàn)這樣的效果。
這種效果就有點(diǎn)想我們平常輸入錯(cuò)誤時(shí)的那個(gè)提示了,還有其他屬性值,這里就不用一一列舉了。
使用Struts2的校驗(yàn)框架
XML配置方式校驗(yàn)。
在編碼方式之前被執(zhí)行。
1) 針對(duì)要校驗(yàn)的Action類,在同包下編寫一個(gè)名為:Action類名-validation.xml校驗(yàn)規(guī)則文件。
2) 在校驗(yàn)規(guī)則文件中添加校驗(yàn)規(guī)則:具體的校驗(yàn)器名,參數(shù)可參看Struts2的reference或Struts2的API。
a) Field校驗(yàn):針對(duì)Action類中每個(gè)非自定義類型的Field進(jìn)行校驗(yàn)的規(guī)則。
<field name="要校驗(yàn)的Field名"> <field-validator type="校驗(yàn)規(guī)則器名" short-circuit="是否要短路徑校驗(yàn)(默認(rèn)是false)"> <param name="校驗(yàn)器要使用的參數(shù)名">值</param> <message>校驗(yàn)失敗時(shí)的提示消息</message> </field-validator> <!-- 還可添加其它的校驗(yàn)規(guī)則 --> </field>
b) 非Field校驗(yàn):針對(duì)Action類的某些Field使用OGNL表達(dá)進(jìn)行組合校驗(yàn)。
<validator type="fieldexpression"> <param name="fieldName">pwd</param> <param name="fieldName">pwd2</param> <param name="expression"><![CDATA[pwd==pwd2]]></param><!-- OGNL表達(dá)式 --> <message>確認(rèn)密碼和密碼輸入不一致</message> </validator>
c) visitor校驗(yàn):主要是用來校驗(yàn)Action類中的自定義類型Field。(針對(duì)使用模型驅(qū)動(dòng)方式時(shí))
i) 在Action類的的校驗(yàn)規(guī)則文件中針對(duì)自定義類型Field使用visitor校驗(yàn)規(guī)則。
<!-- 針對(duì)自定義Field使用visitor校驗(yàn) --> <field name="user"> <field-validator type="required" short-circuit="true"> <message>用戶的信息必填</message><!-- 消息前綴 --> </field-validator> <field-validator type="visitor"><!-- 指定為visitor校驗(yàn)規(guī)則 --> <param name="context">userContext</param><!-- 指定本visitor校驗(yàn)的上下文名 --> <param name="appendPrefix">true</param><!-- 是否要添加校驗(yàn)失敗消息的前綴 --> <message>用戶的</message><!-- 消息前綴 --> </field-validator> </field>
ii) 針對(duì)visitor的Field編寫一個(gè)校驗(yàn)規(guī)則文件.文件名為: visitor字段類型名[-visitor校驗(yàn)的上下文名]-validation.xml. 例如: 本例中的文件名為User-userContext-validation.xml
注意: 此文件要存放到visitor字段類型所在的包下.
iii) 在visitor的Field校驗(yàn)規(guī)則文件中針對(duì)要校驗(yàn)的Field添加校驗(yàn)規(guī)則.
我們還可以不重寫validate方法,而通過增加校驗(yàn)配置文件來進(jìn)行數(shù)據(jù)校驗(yàn)。這個(gè)校驗(yàn)配置文件通過使用Struts2已有的校驗(yàn)器來完成對(duì)表單域的校驗(yàn),下面以requiredstring校驗(yàn)器為例,這個(gè)校驗(yàn)器是一個(gè)必填校驗(yàn)器,指定某個(gè)表單域必須輸入。
下面是這個(gè)校驗(yàn)配置文件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>密碼長(zhǎng)度應(yīng)該在${minLength}--${maxLength}位之間</message> </field-validator> </field> </validators>
注意:這個(gè)校驗(yàn)配置文件必須遵守下面兩個(gè)規(guī)則:
1、該文件命運(yùn)格式必須是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; //驗(yàn)證的方法,會(huì)對(duì)所有的Action起作用 @Override public void validate() { if(user.getUname().length()==0){ addFieldError("uname", "用戶名不能為空!"); } if(user.getUpwd().length()==0){ addFieldError("upwd", "密碼不能為空!"); } } //處理業(yè)務(wù)的方法 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{ //登錄失敗,返回 error return 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 數(shù)據(jù)校驗(yàn)功能及校驗(yàn)問題的解決方案,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Maven本地倉(cāng)庫(kù)的配置以及修改默認(rèn).m2倉(cāng)庫(kù)位置
今天小編就為大家分享一篇關(guān)于Maven本地倉(cāng)庫(kù)的配置以及修改默認(rèn).m2倉(cāng)庫(kù)位置的文章,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-10-10基于Springboot實(shí)現(xiàn)送水公司信息管理系統(tǒng)
這篇文章主要介紹了基于Springboot實(shí)現(xiàn)送水公司信息管理,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01詳解Spring boot+CXF開發(fā)WebService Demo
這篇文章主要介紹了詳解Spring boot+CXF開發(fā)WebService Demo,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-05-05mybatis返回類型map時(shí)如何將key大寫轉(zhuǎn)為小寫
這篇文章主要介紹了mybatis返回類型map時(shí)實(shí)現(xiàn)將key大寫轉(zhuǎn)為小寫操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06windows系統(tǒng)配置Java開發(fā)環(huán)境變量
這篇文章主要介紹了windows系統(tǒng)配置Java開發(fā)環(huán)境變量,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2021-12-12Java批量向PDF文件中添加圖像水印實(shí)現(xiàn)細(xì)節(jié)
這篇文章主要為大家介紹了Java批量向PDF文件中添加圖像水印實(shí)現(xiàn)細(xì)節(jié),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05