通過繼承ActionSupport類來完成Action開發(fā),ActionSupport類不僅對Action接口進行簡單實現(xiàn), 同時增加了驗證、本地化等支持 。真實開發(fā)中自定義Action都需要繼承該類。對用戶登錄添加表單驗證功能
ActionSupport類的作用:
struts2不要求我們自己設計的action類繼承任何的struts基類或struts接口,但是我們?yōu)榱朔奖銓崿F(xiàn)我們自己的action,大多數(shù)情況下都會繼承com.opensymphony.xwork2.ActionSupport類,并重寫此類里的public String execute() throws Exception方法。因為此類中實現(xiàn)了很多的實用借口,提供了很多默認方法,這些默認方法包括國際化信息的方法、默認的處理用戶請求的方法等,這樣可以大大的簡化Acion的開發(fā)。 Struts2中通常直接使用Action來封裝HTTP請求參數(shù),因此,Action類里還應該包含與請求參數(shù)對應的屬性,并且為屬性提供對應的getter和setter方法。
那么Action 接口和 ActionSupport類的區(qū)別是什么呢?
Action接口有:
1
2
3
4
5
|
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; |
可以看到有五個靜態(tài)常量和返回類型為String 的execute()
而Actionsupport這個工具類在實現(xiàn)了Action接口的基礎上還定義了一個validate()方法,重寫該方法,它會在execute()方法之前執(zhí)行,如校驗失敗,會轉入input處,必須在配置該Action時配置input屬性。
另外,Actionsupport還提供了一個getText(String key)方法還實現(xiàn)國際化,該方法從資源文件上獲取國際化信息.
這樣在自定義標簽時可以定義一個變量為new actionsupport對象實現(xiàn)國際化。
Actionsupport類有(源碼):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
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; } |
可以看到里面有很多的方法,但我們很明顯看到有一個我們很了解的,validate(),數(shù)據(jù)校驗的方法。通過這個方法,我們可以登錄時,用戶名和密碼為空的提示,或其他··
現(xiàn)在舉一個簡單的例子:當用戶名和密碼為空,給客戶一個友好提示。
下面通過兩種方式來闡述Struts 2的數(shù)據(jù)校驗功能。
1. 編碼方式校驗
1) Action一定要繼承自ActionSupport
2) 針對某個要進行校驗的請求處理方法編寫一個 public void validateXxx()方法,在方法內部進行表單數(shù)據(jù)校驗.
3) 也可針對所有的請求處理方法編寫public void validate()方法。
4) 在校驗方法中,可以通過addFieldError()方法來添加字段校驗錯誤消息。
5) 當校驗失敗時,Struts框架會自動跳轉到name為input的Result頁面。在校驗失敗頁面中,可以使用<s:fielderror/>來顯示錯誤消息
6) 簡單,靈活。但重用性不高
重寫validate方法
1.我們編寫的Action一般繼承與ActionSupport,而ActionSupport不僅實現(xiàn)了Action接口,還實現(xiàn)了Validatable接口,提供了數(shù)據(jù)校驗功能。在Validatable接口中定義一個validate方法,重寫該方法,如果校驗表單輸入域出現(xiàn)錯誤,則將錯誤添加到ActionSupport類的fieldError域中,然后通過OGNL表達式輸出。
下面是用戶登錄校驗界面:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<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> |
用戶輸入數(shù)據(jù)后,提交到LoginValidateAction 中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
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" , "密碼不能為空!" ); } } //處理業(yè)務的方法 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方法,該方法會在執(zhí)行excute方法之前執(zhí)行,如果執(zhí)行該方法之后,Action類的filedError中包含了數(shù)據(jù)校驗錯誤,請求將被轉發(fā)到input邏輯視圖。
struts.xml配置如下:
1
2
3
4
5
6
7
8
9
|
<!-- 數(shù)據(jù)校驗 --> <action name= "LoginValidateAction" class = "cn.struts2.action.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中,加上下一行代碼就可以了。
1
|
<constant name= "struts.ui.theme" value= "simple" /> |
代表所有的頁面采用的都是 simple主題了,這時它輸出的頁面,不回添加任何多余的代碼,比如 table tr td 等,我們就可以像其他編輯頁面的方式編輯頁面的風格。
現(xiàn)在再來看看,錯誤的提示格式
我們可以通過設置這樣一個標簽:
1
|
<s:property value= "errors.uname[0]" /> |
把這個標簽注釋掉:
1
|
<div style= "color:red" ><s:fielderror/></div> |
但我們設置成 這樣時,會出現(xiàn)這樣的效果。
這種效果就有點想我們平常輸入錯誤時的那個提示了,還有其他屬性值,這里就不用一一列舉了。
使用Struts2的校驗框架
XML配置方式校驗。
在編碼方式之前被執(zhí)行。
1) 針對要校驗的Action類,在同包下編寫一個名為:Action類名-validation.xml校驗規(guī)則文件。
2) 在校驗規(guī)則文件中添加校驗規(guī)則:具體的校驗器名,參數(shù)可參看Struts2的reference或Struts2的API。
a) Field校驗:針對Action類中每個非自定義類型的Field進行校驗的規(guī)則。
1
2
3
4
5
6
7
|
<field name= "要校驗的Field名" > <field-validator type= "校驗規(guī)則器名" short -circuit= "是否要短路徑校驗(默認是false)" > <param name= "校驗器要使用的參數(shù)名" >值</param> <message>校驗失敗時的提示消息</message> </field-validator> <!-- 還可添加其它的校驗規(guī)則 --> </field> |
b) 非Field校驗:針對Action類的某些Field使用OGNL表達進行組合校驗。
1
2
3
4
5
6
|
<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類的的校驗規(guī)則文件中針對自定義類型Field使用visitor校驗規(guī)則。
1
2
3
4
5
6
7
8
9
10
11
|
<!-- 針對自定義Field使用visitor校驗 --> <field name= "user" > <field-validator type= "required" short -circuit= "true" > <message>用戶的信息必填</message><!-- 消息前綴 --> </field-validator> <field-validator type= "visitor" ><!-- 指定為visitor校驗規(guī)則 --> <param name= "context" >userContext</param><!-- 指定本visitor校驗的上下文名 --> <param name= "appendPrefix" > true </param><!-- 是否要添加校驗失敗消息的前綴 --> <message>用戶的</message><!-- 消息前綴 --> </field-validator> </field> |
ii) 針對visitor的Field編寫一個校驗規(guī)則文件.文件名為: visitor字段類型名[-visitor校驗的上下文名]-validation.xml. 例如: 本例中的文件名為User-userContext-validation.xml
注意: 此文件要存放到visitor字段類型所在的包下.
iii) 在visitor的Field校驗規(guī)則文件中針對要校驗的Field添加校驗規(guī)則.
我們還可以不重寫validate方法,而通過增加校驗配置文件來進行數(shù)據(jù)校驗。這個校驗配置文件通過使用Struts2已有的校驗器來完成對表單域的校驗,下面以requiredstring校驗器為例,這個校驗器是一個必填校驗器,指定某個表單域必須輸入。
下面是這個校驗配置文件LoginValidateAction-validation.xml的寫法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<?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> |
注意:這個校驗配置文件必須遵守下面兩個規(guī)則:
1、該文件命運格式必須是Action類名-validation.xml,例如本例中該文件名為:LoginValidateAction-validation.xml
2、該文件必須與Action類的class文件位于同一路徑下,本例中文件位于
LoginValidateAction類的代碼還是一樣:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
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" , "密碼不能為空!" ); } } //處理業(yè)務的方法 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ù)校驗功能及校驗問題的解決方案,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網(wǎng)站的支持!
原文鏈接:http://www.cnblogs.com/whyhappy/p/5831937.html