[关闭]
@liayun 2016-10-03T10:03:18.000000Z 字数 13516 阅读 1634

Struts2框架进阶(三)

Struts2框架学习


这是Struts2框架进阶三。废话不多说,直接进入正文。

输入校验

在Struts2中,我们可以实现对action的所有方法进行校验或者对action的指定方法进行校验。
对于输入校验,Struts2提供了两种实现方法:

手工编写代码实现输入校验

通过重写validate()或validateXxx()方法实现,validate()方法会校验action中所有与execute方法签名相同的方法。validateXxx()只会校验action中方法名为Xxx的方法。其中Xxx的第一个字母要大写。当某个数据校验失败时,我们应该调用addFieldError()方法往系统的fieldErrors添加校验失败信息(为了使用addFieldError()方法,action可以继承ActionSupport ),如果系统的fieldErrors包含失败信息,Struts2会将请求转发到名为input的result,在input视图中可以通过<s:fielderror/>显示失败信息。

对action中所有方法进行输入校验

首先我们编写struts.xml配置文件的内容为:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE struts PUBLIC
  3. "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
  4. "http://struts.apache.org/dtds/struts-2.3.dtd">
  5. <struts>
  6. <package name="person" namespace="/person" extends="struts-default">
  7. <action name="manage_*" class="cn.itcast.action.PersonAction" method="{1}">
  8. <result name="input">/index.jsp</result>
  9. <result name="message">/WEB-INF/page/message.jsp</result>
  10. </action>
  11. </package>
  12. </struts>

接着我们在WebRoot根目录下创建出一个jsp页面——index.jsp,用于收集用户填写的信息。

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  7. <title>输入校验</title>
  8. </head>
  9. <body>
  10. <form action="${pageContext.request.contextPath }/person/manage_save.action" method="post">
  11. 用户名:<input type="text" name="username">不能为空<br/>
  12. 手机号:<input type="text" name="mobile">不能为空,并且要符合手机好的格式:1,3/5/8,后面是9个数字<br/>
  13. <input type="submit" value="提交">
  14. </form>
  15. </body>
  16. </html>

我们还要在WEB-INF/page/目录下创建出一个全局消息显示页面——message.jsp。

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  7. <title>结果</title>
  8. </head>
  9. <body>
  10. ${message }
  11. </body>
  12. </html>

最后我们在cn.itcast.action包下创建一个Action——PersonAction.java。

  1. public class PersonAction extends ActionSupport {
  2. private String username;
  3. private String mobile;
  4. public String getUsername() {
  5. return username;
  6. }
  7. public void setUsername(String username) {
  8. this.username = username;
  9. }
  10. public String getMobile() {
  11. return mobile;
  12. }
  13. public void setMobile(String mobile) {
  14. this.mobile = mobile;
  15. }
  16. public String update() {
  17. ActionContext.getContext().put("message", "更新成功");
  18. return "message";
  19. }
  20. public String save() {
  21. ActionContext.getContext().put("message", "保存成功");
  22. return "message";
  23. }
  24. }

以上准备工作做好之后,开始对PersonAction.java中的所有方法进行输入校验。我们只须在PersonAction类中添加如下方法即可:

  1. @Override
  2. public void validate() { // 会对action中的所有方法进行校验
  3. if (this.username==null || "".equals(this.username.trim())) {
  4. this.addFieldError("username", "用户名不能为空"); // 输出校验错误信息
  5. }
  6. if (this.mobile==null || "".equals(this.mobile.trim())) {
  7. this.addFieldError("mobile", "手机号不能为空");
  8. } else {
  9. if (!Pattern.compile("^1[358]\\d{9}$").matcher(this.mobile).matches()) {
  10. this.addFieldError("mobile", "手机号格式不正确");
  11. }
  12. }
  13. }

如果验证失败后,请求将转发至input视图:

  1. <result name="input">/index.jsp</result>

在index.jsp页面中还要使用Struts2标签<s:fielderror/>显示校验失败信息。注意,还要在页面头部添加:

  1. <%@ taglib="/struts-tags" prefix="s" %>

这样,index.jsp页面的内容就为:

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <%@ taglib uri="/struts-tags" prefix="s" %>
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  5. <html>
  6. <head>
  7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  8. <title>输入校验</title>
  9. </head>
  10. <body>
  11. <s:fielderror />
  12. <form action="${pageContext.request.contextPath }/person/manage_save.action" method="post">
  13. 用户名:<input type="text" name="username">不能为空<br/>
  14. 手机号:<input type="text" name="mobile">不能为空,并且要符合手机好的格式:1,3/5/8,后面是9个数字<br/>
  15. <input type="submit" value="提交">
  16. </form>
  17. </body>
  18. </html>

这样,我们就实现了对action中的所有方法进行输入校验。大家亦可自行测试。

对action指定方法进行校验

若是要对PersonAction.java中的update()方法进行输入校验,只须在PersonAction类中添加如下方法即可:

  1. public void validateUpdate() { // 会对action中的update()方法进行校验
  2. if (this.username==null || "".equals(this.username.trim())) {
  3. this.addFieldError("username", "用户名不能为空"); // 输出校验错误信息
  4. }
  5. if (this.mobile==null || "".equals(this.mobile.trim())) {
  6. this.addFieldError("mobile", "手机号不能为空");
  7. } else {
  8. if (!Pattern.compile("^1[358]\\d{9}$").matcher(this.mobile).matches()) {
  9. this.addFieldError("mobile", "手机号格式不正确");
  10. }
  11. }
  12. }

这样,我们就实现了对action中的指定方法进行输入校验。大家亦可自行测试。

输入校验的流程

  1. 点击提交按钮后,类型转换器对请求参数执行类型转换,并把转换后的值赋给action中的属性。
  2. 如果在执行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext,conversionError拦截器将异常信息封装到fieldErrors里,然后执行第3步。如果类型转换没有出现异常,则直接进入第3步。
  3. 系统通过反射技术先调用action中的validateXxx()方法,Xxx为方法名。
  4. 再调用action中的validate()方法。
  5. 经过上面4步,如果系统中的fieldErrors存在错误信息(即存放错误信息的集合不为空且size大于0),系统自动将请求转发至名称为input的视图。如果系统中的fieldErrors没有任何错误信息,系统将执行action中的处理方法。

第2步说明了进入input视图有两种情况:

如果validate()方法中没有一行代码,但是还会进入input视图,原因就应该是类型转换失败了。我们举例来说明这一点。
我们首先修改index.jsp的页面内容为:

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <%@ taglib uri="/struts-tags" prefix="s" %>
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  5. <html>
  6. <head>
  7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  8. <title>输入校验</title>
  9. </head>
  10. <body>
  11. <s:fielderror />
  12. <form action="${pageContext.request.contextPath }/person/manage_update.action" method="post">
  13. 用户名:<input type="text" name="username">不能为空<br/>
  14. 生日:<input type="text" name="birthday"><br/>
  15. 手机号:<input type="text" name="mobile">不能为空,并且要符合手机好的格式:1,3/5/8,后面是9个数字<br/>
  16. <input type="submit" value="提交">
  17. </form>
  18. </body>
  19. </html>

接着修改PersonAction类的代码为:

  1. public class PersonAction extends ActionSupport {
  2. private String username;
  3. private String mobile;
  4. private Date birthday;
  5. public Date getBirthday() {
  6. return birthday;
  7. }
  8. public void setBirthday(Date birthday) {
  9. this.birthday = birthday;
  10. }
  11. public String getUsername() {
  12. return username;
  13. }
  14. public void setUsername(String username) {
  15. this.username = username;
  16. }
  17. public String getMobile() {
  18. return mobile;
  19. }
  20. public void setMobile(String mobile) {
  21. this.mobile = mobile;
  22. }
  23. public String update() {
  24. ActionContext.getContext().put("message", "更新成功");
  25. return "message";
  26. }
  27. public String save() {
  28. ActionContext.getContext().put("message", "保存成功");
  29. return "message";
  30. }
  31. public void validateUpdate() { // 会对action中的update()方法进行校验
  32. }
  33. }

测试如下:
记得要插入.GIF的图片
验证了这一点。

基于XML配置方式实现输入校验

基于XML配置方式实现对action的所有方法进行校验

若要基于XML配置方式实现输入校验,则Action类需要继承ActionSupport,然后还得提供校验文件,如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE validators PUBLIC
  3. "-//Apache Struts//XWork Validator 1.0.3//EN"
  4. "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
  5. <validators>
  6. <field name="username">
  7. <field-validator type="requiredstring">
  8. <param name="trim">true</param>
  9. <message>用户名不能为空!</message>
  10. </field-validator>
  11. </field>
  12. </validators>

初学者可能不知道以上的校验文件怎么写,但没关系,Struts2框架给开发人员提供了一些案例,我们可以拷贝其中的校验文件到我们的项目中,然后修修改改。如我们可以在诸如...\struts-2.3.24\apps\struts2-blank\WEB-INF\classes\example目录下找到这样的校验文件——Login-validation.xml,打开:

  1. <!DOCTYPE validators PUBLIC
  2. "-//Apache Struts//XWork Validator 1.0.2//EN"
  3. "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
  4. <validators>
  5. <field name="username">
  6. <field-validator type="requiredstring">
  7. <message key="requiredstring"/>
  8. </field-validator>
  9. </field>
  10. <field name="password">
  11. <field-validator type="requiredstring">
  12. <message key="requiredstring"/>
  13. </field-validator>
  14. </field>
  15. </validators>

发现该校验文件使用的是XWork Validator 1.0.2版本,该版本对有些输入校验不友好,所以就不要选用这个版本了,最好是选用1.0.3版本。总之,不要使用XWork Validator 1.0.2这个版本
好了,我们还是回到一开始的校验文件。在这个校验文件中,对action中字符串类型的username属性进行验证,首先要求调用trim()方法去掉空格,然后判断用户名是否为空。该文件需要和action类放在同一个包下,文件的取名应遵守ActionClassName-validation.xml规则,其中ActionClassName为action的简单类名,-validation为固定写法。如果Action类为cn.itcast.action.UserAction,那么该文件的取名应为:UserAction-validation.xml。
我们把注意力集中在这段代码上面:

  1. <field name="username">
  2. <field-validator type="requiredstring">
  3. <param name="trim">true</param>
  4. <message>用户名不能为空!</message>
  5. </field-validator>
  6. </field>

上面指定的校验器requiredstring是由系统提供的,系统提供了能满足大部分验证需求的校验器,这些校验器的定义可以在xwork-core-2.x.x.jar中的com.opensymphony.xwork2.validator.validators下的default.xml中找到。
下面我们就来详细说明系统提供的校验器。
系统提供的校验器如下:

弄清楚上面的知识点之后,我们就基于XML配置方式实现对action的所有方法进行校验。
首先我们将PersonAction类的代码修改为:

  1. public class PersonAction extends ActionSupport {
  2. private String username;
  3. private String mobile;
  4. public String getUsername() {
  5. return username;
  6. }
  7. public void setUsername(String username) {
  8. this.username = username;
  9. }
  10. public String getMobile() {
  11. return mobile;
  12. }
  13. public void setMobile(String mobile) {
  14. this.mobile = mobile;
  15. }
  16. public String update() {
  17. ActionContext.getContext().put("message", "更新成功");
  18. return "message";
  19. }
  20. public String save() {
  21. ActionContext.getContext().put("message", "保存成功");
  22. return "message";
  23. }
  24. }

接着我们还要修改index.jsp页面的内容为:

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <%@ taglib uri="/struts-tags" prefix="s" %>
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  5. <html>
  6. <head>
  7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  8. <title>输入校验</title>
  9. </head>
  10. <body>
  11. <s:fielderror />
  12. <form action="${pageContext.request.contextPath }/person/manage_save.action" method="post">
  13. 用户名:<input type="text" name="username">不能为空<br/>
  14. 手机号:<input type="text" name="mobile">不能为空,并且要符合手机好的格式:1,3/5/8,后面是9个数字<br/>
  15. <input type="submit" value="提交">
  16. </form>
  17. </body>
  18. </html>

最后我们就要在cn.itcast.action包下提供校验文件了,文件名必须为PersonAction-validation.xml。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE validators PUBLIC
  3. "-//Apache Struts//XWork Validator 1.0.3//EN"
  4. "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
  5. <validators>
  6. <field name="username">
  7. <field-validator type="requiredstring">
  8. <param name="trim">true</param>
  9. <message>用户名不能为空!</message>
  10. </field-validator>
  11. </field>
  12. <field name="mobile">
  13. <field-validator type="requiredstring">
  14. <message>手机号不能为空!</message>
  15. </field-validator>
  16. <field-validator type="regex">
  17. <param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
  18. <message>手机号格式不正确!</message>
  19. </field-validator>
  20. </field>
  21. </validators>

测试,发现正则表达式校验器不起作用,原因不知为何

基于XML配置方式实现对action的指定方法进行输入校验

当校验文件的取名为ActionClassName-validation.xml时,会对action中的所有处理方法实施输入验证。如果你只需要对action中的某个处理方法实施验证,那么,校验文件的取名应为:ActionClassName-ActionName-validation.xml,其中ActionName为struts.xml中为action配置的名称。例如:在实际应用中,常有以下配置:

  1. <action name="user_*" class="cn.itcast.action.UserAction" method="{1}">
  2. <result name="success">/WEB-INF/page/message.jsp</result>
  3. <result name="input">/WEB-INF/page/addUser.jsp</result>
  4. </action>

UserAction中有以下两个处理方法:

  1. public String add() throws Exception{
  2. ....
  3. }
  4. public String update() throws Exception{
  5. ....
  6. }

如果我们要访问UserAction类中的add()方法,那极有可能在浏览器中输入这样的URL地址:.../person/user_add.action,这时我们有必要知道Struts2框架是如何解析这样的URL地址的。
Struts2框架在寻找action的时候,先解析出:namespace=/person,然后再解析出:ActionName=user_add,也即是说,ActionName是路径中的,而不是<action>标签中的name。所以,

现在我们基于XML配置方式只实现对PersonAction的update()方法进行输入校验。我们只须在cn.itcast.action包下提供校验文件即可,校验文件必须得为PersonAction-manage_update-validation.xml。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE validators PUBLIC
  3. "-//Apache Struts//XWork Validator 1.0.3//EN"
  4. "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
  5. <validators>
  6. <field name="username">
  7. <field-validator type="requiredstring">
  8. <param name="trim">true</param>
  9. <message>用户名不能为空!</message>
  10. </field-validator>
  11. </field>
  12. <field name="mobile">
  13. <field-validator type="requiredstring">
  14. <message>手机号不能为空!</message>
  15. </field-validator>
  16. <field-validator type="regex">
  17. <param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
  18. <message>手机号格式不正确!</message>
  19. </field-validator>
  20. </field>
  21. </validators>

测试,发现正则表达式校验器不起作用,原因不知为何

总结

当为某个action提供了ActionClassName-validation.xml和ActionClassName-ActionName-validation.xml两种规则的校验文件时,系统按下面顺序寻找校验文件:

  1. AconClassName-validation.xml
  2. ActionClassName-ActionName-validation.xml

系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有校验文件时,会把校验文件里的所有校验规则汇总,然后全部应用于处理方法的校验。如果两个校验文件中指定的校验规则冲突,则只使用后面文件中的校验规则。
当action继承了另一个action,父类action的校验文件会先被搜索到。假设UserAction继承BaseAction, UserAction在struts.xml中的配置如下:

  1. <action name="user" class="cn.itcast.action.UserAction" method="{1}">
  2. .....
  3. </action>

访问上面名为user的action,系统先搜索到BaseAction-validation.xml, BaseAction-user-validation.xml,接着搜索到UserAction-validation.xml, UserAction-user-validation.xml。校验规则是这四个文件的总和。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注