由于web的开放性,网络上的所有的浏览者都可以自由使用该应用,为了防止非法输入进入系统,有必要需要对用户的输入进行校验,其中输入校验又分为客户端校验和服务器端校验,客户端校验主要通过JavaScript代码完成,服务器端校验主要通过在应用中编程实现。这里主要对服务器端校验进行说明一下,Struts2为我们提供了两种服务器端的校验:
1.手动输入校验:
要实现校验的类需要继承ActionSupport类,并重写validate()方法(该方法会对action中的所有方法进行校验),如有以下类:
Java代码
1.public class UserBean extends ActionSupport{
2. private String username;
3. private String password;
4.
5. public String getPassword() {
6. return password;
7. }
8.
9. public void setPassword(String password) {
10. this.password = password;
11. }
12.
13. public String getUsername() {
14. return username;
15. }
16.
17. public void setUsername(String username) {
18. this.username = username;
19. }
20.
21. public String update() {
22. ActionContext.getContext().put("message", "更新成功");
23. return "message";
24. }
25.
26. public String save() {
27. ActionContext.getContext().put("message", "保存成功");
28. return "message";
29. }
30.
31. public void validate() {
32. System.out.println("validate方法校验");
33. if(this.username == null || "".equals(this.username.trim())) {
34. this.addFieldError("username", "用户名不能为空!");
35. }
36.
37. if(password != null && !Pattern.matches("^[A-Za-z0-9]+$", password.trim())) {
38. this.addFieldError("password", "密码不能为空,且必须是字母和数字!");
39. }
40. }
41.}
public class UserBean extends ActionSupport{
private String username;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String update() {
ActionContext.getContext().put("message", "更新成功");
return "message";
}
public String save() {
ActionContext.getContext().put("message", "保存成功");
return "message";
}
public void validate() {
System.out.println("validate方法校验");
if(this.username == null || "".equals(this.username.trim())) {
this.addFieldError("username", "用户名不能为空!");
}
if(password != null && !Pattern.matches("^[A-Za-z0-9]+$", password.trim())) {
this.addFieldError("password", "密码不能为空,且必须是字母和数字!");
}
}
} 上面的UserBean类有sava()和update()两种方法,并在validate()方法中对用户名和密码进行了校验。
Struts.xml的配置如下:
Xml代码
1.<struts>
2. <constant name="struts.devMode" value="true" />
3. <package name="user" namespace="/user" extends="struts-default">
4. <action name="user_*" class="com.struts2.UserBean" method="{1}">
5. <result name="input">/index.jsp</result>
6. <result name="message">/message.jsp</result>
7. </action>
8. </package>
9.</struts>
<struts>
<constant name="struts.devMode" value="true" />
<package name="user" namespace="/user" extends="struts-default">
<action name="user_*" class="com.struts2.UserBean" method="{1}">
<result name="input">/index.jsp</result>
<result name="message">/message.jsp</result>
</action>
</package>
</struts> 输入界面(index.jsp)代码如下:
Html代码
1.<html>
2. <body>
3. <s:fielderror/>
4. <form action="${pageContext.request.contextPath}/user/user_update" method="post">
5. 用户名:<input type="text" name="username"/><br/>
6. 密 码:<input type="password" name="password"/><br/>
7. <input type="submit" value="确认"/>
8. </form>
9. </body>
10.</html>
<html>
<body>
<s:fielderror/>
<form action="${pageContext.request.contextPath}/user/user_update" method="post">
用户名:<input type="text" name="username"/><br/>
密 码:<input type="password" name="password"/><br/>
<input type="submit" value="确认"/>
</form>
</body>
</html><s:fielderror/>标签的作用:一旦发现校验失败,就把校验失败的提示通过addFieldError方法添加进系统的fieldError中,然后通过输入界面提示错误的信息,以便用户更好的进行输入。
输入界面(index.jps)如下时:
用户名:
密 码:
当用户名和密码都为空时,index.jsp会出现错误提示信息:
•用户名不能为空!
•密码不能为空,且必须是字母和数字!
如果输入的参数类型转换失败,也会返回input逻辑视图,实际上,即使是类型转换失败,系统一样会执行validate()方法进行数据校验
如果只想对UserBean中的某个方法进行校验,则需提供一个validateXxx()方法,其中Xxx即是Action对应的处理逻辑方法,下面对UserBean中的Update()进行校验,添加validateUpdate()方法后,修改后的UserBean如下:
Java代码
1.public class UserBean extends ActionSupport{
2. private String username;
3. private String password;
4.
5. public String getPassword() {
6. return password;
7. }
8.
9. public void setPassword(String password) {
10. this.password = password;
11. }
12.
13. public String getUsername() {
14. return username;
15. }
16.
17. public void setUsername(String username) {
18. this.username = username;
19. }
20.
21. public String update() {
22. ActionContext.getContext().put("message", "更新成功");
23. return "message";
24. }
25.
26. public String save() {
27. ActionContext.getContext().put("message", "保存成功");
28. return "message";
29. }
30.
31. public void validate() {
32. System.out.println("validate方法校验");
33. if(this.username == null || "".equals(this.username.trim())) {
34. this.addFieldError("username", "用户名不能为空!");
35. }
36.
37. if(password != null && !Pattern.matches("^[A-Za-z0-9]+$", password.trim())) {
38. this.addFieldError("password", "密码不能为空,且必须是字母和数字!");
39. }
40. }
41.
42. public void validateUpdate() {
43. System.out.println("validateUpdate方法校验");
44. if(this.username == null || "".equals(this.username.trim())) {
45. this.addFieldError("username", "validateUpdate()方法,用户名不能为空!");
46. }
47.
48. if(password != null && !Pattern.matches("^[A-Za-z0-9]+$", password.trim())) {
49. this.addFieldError("password", "validateUpdate()方法,密码不能为空,且必须是字母和数字的组合!");
50. }
51. }
52.}
public class UserBean extends ActionSupport{
private String username;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String update() {
ActionContext.getContext().put("message", "更新成功");
return "message";
}
public String save() {
ActionContext.getContext().put("message", "保存成功");
return "message";
}
public void validate() {
System.out.println("validate方法校验");
if(this.username == null || "".equals(this.username.trim())) {
this.addFieldError("username", "用户名不能为空!");
}
if(password != null && !Pattern.matches("^[A-Za-z0-9]+$", password.trim())) {
this.addFieldError("password", "密码不能为空,且必须是字母和数字!");
}
}
public void validateUpdate() {
System.out.println("validateUpdate方法校验");
if(this.username == null || "".equals(this.username.trim())) {
this.addFieldError("username", "validateUpdate()方法,用户名不能为空!");
}
if(password != null && !Pattern.matches("^[A-Za-z0-9]+$", password.trim())) {
this.addFieldError("password", "validateUpdate()方法,密码不能为空,且必须是字母和数字的组合!");
}
}
} 当用户名和密码都为空时,index.jsp会出现错误提示信息:
•validateUpdate()方法,用户名不能为空!
•用户名不能为空!
•validateUpdate()方法,密码不能为空,且必须是字母和数字的组合!
•密码不能为空,且必须是字母和数字!
从提示信息可以看出,当用户向Update方法发送请求时,该Action内的validate方法和validateUpdate方法都会起作用,而且validateUpdate方法首先被调用
2.基于xml配置的输入校验:
使用基于xml配置方式实现输入校验时,Action也需要继承ActionSupport类,还以上面的例子来说明,UserBean类如下:
Java代码
1.public class UserBean extends ActionSupport{
2. private String username;
3. private String password;
4.
5. public String getPassword() {
6. return password;
7. }
8.
9. public void setPassword(String password) {
10. this.password = password;
11. }
12.
13. public String getUsername() {
14. return username;
15. }
16.
17. public void setUsername(String username) {
18. this.username = username;
19. }
20.
21. public String update() {
22. ActionContext.getContext().put("message", "更新成功");
23. return "message";
24. }
25.
26. public String save() {
27. ActionContext.getContext().put("message", "保存成功");
28. return "message";
29. }
30.}
public class UserBean extends ActionSupport{
private String username;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String update() {
ActionContext.getContext().put("message", "更新成功");
return "message";
}
public String save() {
ActionContext.getContext().put("message", "保存成功");
return "message";
}
} 此外还需提供校验文件,校验和action放在同一个包下,文件的取名格式为:ActionClassName-validation.xml,其中ActionClassName为action的类名,可以改变,后面的-validate.xml部分是固定写法,如此处的文件名就应该为UserBean-validation.xml,校验文件代码如下:
Xml代码
1.<validators>
2. <field name="username">
3. <field-validator type="requiredstring">
4. <param name="trim">true</param>
5. <message>用户名不能为空</message>
6. </field-validator>
7. </field>
8.
9. <field name="password">
10. <field-validator type="requiredstring">
11. <message>密码不能为空</message>
12. </field-validator>
13.
14. <field-validator type="regex">
15. <param name="expression"><![CDATA[^[A-Za-z0-9]+$]]></param>
16. <message>密码格式不正确,必须是字母和数字的组合</message>
17. </field-validator>
18. </field>
19.</validators>
<validators>
<field name="username">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message>密码不能为空</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[^[A-Za-z0-9]+$]]></param>
<message>密码格式不正确,必须是字母和数字的组合</message>
</field-validator>
</field>
</validators> 当校验文件的取名为ActionClassName-validate.xml时,会对action中的所有处理方法进行输入校验,如果需要对action的某个方法进行校验,则校验文件的取名应为:ActionClassName-ActionName-validate.xml,其中ActionName为struts.xml中action的名称,如下面的struts.xml配置:
Xml代码
1.<struts>
2. <constant name="struts.devMode" value="true" />
3. <package name="user" namespace="/user" extends="struts-default">
4. <action name="user_*" class="com.struts2.UserBean" method="{1}">
5. <result name="input">/index.jsp</result>
6. <result name="message">/message.jsp</result>
7. </action>
8. </package>
9.</struts>
<struts>
<constant name="struts.devMode" value="true" />
<package name="user" namespace="/user" extends="struts-default">
<action name="user_*" class="com.struts2.UserBean" method="{1}">
<result name="input">/index.jsp</result>
<result name="message">/message.jsp</result>
</action>
</package>
</struts> 如果需要对UserBean中的save()方法进行校验,则文件的名称就为:UserBean-user_save.validation.xml,对update()方法进行校验时,文件的名称就为:UserBean-user_update.xml,而校验文件的内容与 UserBean-validation.xml相同,文件存放在与需要校验的action的同一包下。
基于xml配置输入校验的特点:
当为同一个action提供了ActionClassName-validation.xml和ActionClassName-ActionClassName-validation.xml两种校验文件时,系统按下面的顺序寻找校验文件:
1.ActionClassName-validation.xml
2.ActionClassName-ActionClassName-validation.xml
系统寻找到第一个文件时,还会继续搜索后面的校验文件,当搜索完所有的校验文件时,会把校验文件的所有校验规则进行综合,然后全部应用于action方法的校验,如果两个校验文件中的校验规则发生冲突,则只使用后面校验文件的校验规则。
当action继承了另一个action,则父类action的校验文件会先被搜索到。
Struts2的输入校验流程:
1.类型转换器对请求参数执行类型转换,并把转换后的值设置成Action的属性值
2.如果在执行转换的过程中出现异常,系统会将异常的信息保存到ActionContext中,conversionError拦截器负责将其封装到fieldError里,然后执行第3步,如果转换过程没有出现异常,则直接进入第3步
3.系统通过反射技术调用validateXxx()方法,其中Xxx是即将处理用户请求的处理逻辑所对应的方法名
4.调用Action类里的validate()方法
5.经过上面的4个步骤之后,如果都没有出现fieldError,将调用Action里处理用户请求的处理方法,如果fieldError中存在错误信息,系统将转入input逻辑视图所指定的视图资源
1.手动输入校验:
要实现校验的类需要继承ActionSupport类,并重写validate()方法(该方法会对action中的所有方法进行校验),如有以下类:
Java代码
1.public class UserBean extends ActionSupport{
2. private String username;
3. private String password;
4.
5. public String getPassword() {
6. return password;
7. }
8.
9. public void setPassword(String password) {
10. this.password = password;
11. }
12.
13. public String getUsername() {
14. return username;
15. }
16.
17. public void setUsername(String username) {
18. this.username = username;
19. }
20.
21. public String update() {
22. ActionContext.getContext().put("message", "更新成功");
23. return "message";
24. }
25.
26. public String save() {
27. ActionContext.getContext().put("message", "保存成功");
28. return "message";
29. }
30.
31. public void validate() {
32. System.out.println("validate方法校验");
33. if(this.username == null || "".equals(this.username.trim())) {
34. this.addFieldError("username", "用户名不能为空!");
35. }
36.
37. if(password != null && !Pattern.matches("^[A-Za-z0-9]+$", password.trim())) {
38. this.addFieldError("password", "密码不能为空,且必须是字母和数字!");
39. }
40. }
41.}
public class UserBean extends ActionSupport{
private String username;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String update() {
ActionContext.getContext().put("message", "更新成功");
return "message";
}
public String save() {
ActionContext.getContext().put("message", "保存成功");
return "message";
}
public void validate() {
System.out.println("validate方法校验");
if(this.username == null || "".equals(this.username.trim())) {
this.addFieldError("username", "用户名不能为空!");
}
if(password != null && !Pattern.matches("^[A-Za-z0-9]+$", password.trim())) {
this.addFieldError("password", "密码不能为空,且必须是字母和数字!");
}
}
} 上面的UserBean类有sava()和update()两种方法,并在validate()方法中对用户名和密码进行了校验。
Struts.xml的配置如下:
Xml代码
1.<struts>
2. <constant name="struts.devMode" value="true" />
3. <package name="user" namespace="/user" extends="struts-default">
4. <action name="user_*" class="com.struts2.UserBean" method="{1}">
5. <result name="input">/index.jsp</result>
6. <result name="message">/message.jsp</result>
7. </action>
8. </package>
9.</struts>
<struts>
<constant name="struts.devMode" value="true" />
<package name="user" namespace="/user" extends="struts-default">
<action name="user_*" class="com.struts2.UserBean" method="{1}">
<result name="input">/index.jsp</result>
<result name="message">/message.jsp</result>
</action>
</package>
</struts> 输入界面(index.jsp)代码如下:
Html代码
1.<html>
2. <body>
3. <s:fielderror/>
4. <form action="${pageContext.request.contextPath}/user/user_update" method="post">
5. 用户名:<input type="text" name="username"/><br/>
6. 密 码:<input type="password" name="password"/><br/>
7. <input type="submit" value="确认"/>
8. </form>
9. </body>
10.</html>
<html>
<body>
<s:fielderror/>
<form action="${pageContext.request.contextPath}/user/user_update" method="post">
用户名:<input type="text" name="username"/><br/>
密 码:<input type="password" name="password"/><br/>
<input type="submit" value="确认"/>
</form>
</body>
</html><s:fielderror/>标签的作用:一旦发现校验失败,就把校验失败的提示通过addFieldError方法添加进系统的fieldError中,然后通过输入界面提示错误的信息,以便用户更好的进行输入。
输入界面(index.jps)如下时:
用户名:
密 码:
当用户名和密码都为空时,index.jsp会出现错误提示信息:
•用户名不能为空!
•密码不能为空,且必须是字母和数字!
如果输入的参数类型转换失败,也会返回input逻辑视图,实际上,即使是类型转换失败,系统一样会执行validate()方法进行数据校验
如果只想对UserBean中的某个方法进行校验,则需提供一个validateXxx()方法,其中Xxx即是Action对应的处理逻辑方法,下面对UserBean中的Update()进行校验,添加validateUpdate()方法后,修改后的UserBean如下:
Java代码
1.public class UserBean extends ActionSupport{
2. private String username;
3. private String password;
4.
5. public String getPassword() {
6. return password;
7. }
8.
9. public void setPassword(String password) {
10. this.password = password;
11. }
12.
13. public String getUsername() {
14. return username;
15. }
16.
17. public void setUsername(String username) {
18. this.username = username;
19. }
20.
21. public String update() {
22. ActionContext.getContext().put("message", "更新成功");
23. return "message";
24. }
25.
26. public String save() {
27. ActionContext.getContext().put("message", "保存成功");
28. return "message";
29. }
30.
31. public void validate() {
32. System.out.println("validate方法校验");
33. if(this.username == null || "".equals(this.username.trim())) {
34. this.addFieldError("username", "用户名不能为空!");
35. }
36.
37. if(password != null && !Pattern.matches("^[A-Za-z0-9]+$", password.trim())) {
38. this.addFieldError("password", "密码不能为空,且必须是字母和数字!");
39. }
40. }
41.
42. public void validateUpdate() {
43. System.out.println("validateUpdate方法校验");
44. if(this.username == null || "".equals(this.username.trim())) {
45. this.addFieldError("username", "validateUpdate()方法,用户名不能为空!");
46. }
47.
48. if(password != null && !Pattern.matches("^[A-Za-z0-9]+$", password.trim())) {
49. this.addFieldError("password", "validateUpdate()方法,密码不能为空,且必须是字母和数字的组合!");
50. }
51. }
52.}
public class UserBean extends ActionSupport{
private String username;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String update() {
ActionContext.getContext().put("message", "更新成功");
return "message";
}
public String save() {
ActionContext.getContext().put("message", "保存成功");
return "message";
}
public void validate() {
System.out.println("validate方法校验");
if(this.username == null || "".equals(this.username.trim())) {
this.addFieldError("username", "用户名不能为空!");
}
if(password != null && !Pattern.matches("^[A-Za-z0-9]+$", password.trim())) {
this.addFieldError("password", "密码不能为空,且必须是字母和数字!");
}
}
public void validateUpdate() {
System.out.println("validateUpdate方法校验");
if(this.username == null || "".equals(this.username.trim())) {
this.addFieldError("username", "validateUpdate()方法,用户名不能为空!");
}
if(password != null && !Pattern.matches("^[A-Za-z0-9]+$", password.trim())) {
this.addFieldError("password", "validateUpdate()方法,密码不能为空,且必须是字母和数字的组合!");
}
}
} 当用户名和密码都为空时,index.jsp会出现错误提示信息:
•validateUpdate()方法,用户名不能为空!
•用户名不能为空!
•validateUpdate()方法,密码不能为空,且必须是字母和数字的组合!
•密码不能为空,且必须是字母和数字!
从提示信息可以看出,当用户向Update方法发送请求时,该Action内的validate方法和validateUpdate方法都会起作用,而且validateUpdate方法首先被调用
2.基于xml配置的输入校验:
使用基于xml配置方式实现输入校验时,Action也需要继承ActionSupport类,还以上面的例子来说明,UserBean类如下:
Java代码
1.public class UserBean extends ActionSupport{
2. private String username;
3. private String password;
4.
5. public String getPassword() {
6. return password;
7. }
8.
9. public void setPassword(String password) {
10. this.password = password;
11. }
12.
13. public String getUsername() {
14. return username;
15. }
16.
17. public void setUsername(String username) {
18. this.username = username;
19. }
20.
21. public String update() {
22. ActionContext.getContext().put("message", "更新成功");
23. return "message";
24. }
25.
26. public String save() {
27. ActionContext.getContext().put("message", "保存成功");
28. return "message";
29. }
30.}
public class UserBean extends ActionSupport{
private String username;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String update() {
ActionContext.getContext().put("message", "更新成功");
return "message";
}
public String save() {
ActionContext.getContext().put("message", "保存成功");
return "message";
}
} 此外还需提供校验文件,校验和action放在同一个包下,文件的取名格式为:ActionClassName-validation.xml,其中ActionClassName为action的类名,可以改变,后面的-validate.xml部分是固定写法,如此处的文件名就应该为UserBean-validation.xml,校验文件代码如下:
Xml代码
1.<validators>
2. <field name="username">
3. <field-validator type="requiredstring">
4. <param name="trim">true</param>
5. <message>用户名不能为空</message>
6. </field-validator>
7. </field>
8.
9. <field name="password">
10. <field-validator type="requiredstring">
11. <message>密码不能为空</message>
12. </field-validator>
13.
14. <field-validator type="regex">
15. <param name="expression"><![CDATA[^[A-Za-z0-9]+$]]></param>
16. <message>密码格式不正确,必须是字母和数字的组合</message>
17. </field-validator>
18. </field>
19.</validators>
<validators>
<field name="username">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message>密码不能为空</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[^[A-Za-z0-9]+$]]></param>
<message>密码格式不正确,必须是字母和数字的组合</message>
</field-validator>
</field>
</validators> 当校验文件的取名为ActionClassName-validate.xml时,会对action中的所有处理方法进行输入校验,如果需要对action的某个方法进行校验,则校验文件的取名应为:ActionClassName-ActionName-validate.xml,其中ActionName为struts.xml中action的名称,如下面的struts.xml配置:
Xml代码
1.<struts>
2. <constant name="struts.devMode" value="true" />
3. <package name="user" namespace="/user" extends="struts-default">
4. <action name="user_*" class="com.struts2.UserBean" method="{1}">
5. <result name="input">/index.jsp</result>
6. <result name="message">/message.jsp</result>
7. </action>
8. </package>
9.</struts>
<struts>
<constant name="struts.devMode" value="true" />
<package name="user" namespace="/user" extends="struts-default">
<action name="user_*" class="com.struts2.UserBean" method="{1}">
<result name="input">/index.jsp</result>
<result name="message">/message.jsp</result>
</action>
</package>
</struts> 如果需要对UserBean中的save()方法进行校验,则文件的名称就为:UserBean-user_save.validation.xml,对update()方法进行校验时,文件的名称就为:UserBean-user_update.xml,而校验文件的内容与 UserBean-validation.xml相同,文件存放在与需要校验的action的同一包下。
基于xml配置输入校验的特点:
当为同一个action提供了ActionClassName-validation.xml和ActionClassName-ActionClassName-validation.xml两种校验文件时,系统按下面的顺序寻找校验文件:
1.ActionClassName-validation.xml
2.ActionClassName-ActionClassName-validation.xml
系统寻找到第一个文件时,还会继续搜索后面的校验文件,当搜索完所有的校验文件时,会把校验文件的所有校验规则进行综合,然后全部应用于action方法的校验,如果两个校验文件中的校验规则发生冲突,则只使用后面校验文件的校验规则。
当action继承了另一个action,则父类action的校验文件会先被搜索到。
Struts2的输入校验流程:
1.类型转换器对请求参数执行类型转换,并把转换后的值设置成Action的属性值
2.如果在执行转换的过程中出现异常,系统会将异常的信息保存到ActionContext中,conversionError拦截器负责将其封装到fieldError里,然后执行第3步,如果转换过程没有出现异常,则直接进入第3步
3.系统通过反射技术调用validateXxx()方法,其中Xxx是即将处理用户请求的处理逻辑所对应的方法名
4.调用Action类里的validate()方法
5.经过上面的4个步骤之后,如果都没有出现fieldError,将调用Action里处理用户请求的处理方法,如果fieldError中存在错误信息,系统将转入input逻辑视图所指定的视图资源