概述
在提交表单数据时,如果数据需要保存到数据库,空输入等可能会引发一些异常,为了避免引起用户的输入引起底层异常,通常在进行业务逻辑操作之前,先执行基本的数据校验。
下面通过四种方式来阐述Struts 2的数据校验功能。
校验前准备工作
1.创建实体类
public class UserInfo { private String uname; private String upwd; private String repwd; public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } public String getUpwd() { return upwd; } public void setUpwd(String upwd) { this.upwd = upwd; } public String getRepwd() { return repwd; } public void setRepwd(String repwd) { this.repwd = repwd; } }
2.创建Action
public class LoginAction extends ActionSupport { private UserInfo info; @Override public String execute() throws Exception { return SUCCESS; } public UserInfo getInfo() { return info; } public void setInfo(UserInfo info) { this.info = info; } }
3.jsp页面
<h1>用户注册</h1> <s:fielderror></s:fielderror> <s:form action="aaaaa" method="POST"> <s:textarea label="用户名" name="info.uname"/><br> <s:password label="密码" name="info.upwd"/><br> <s:password label="确认密码" name="info.repwd"/><br> <s:submit value="注册"/>
一 用execute()实现校验
@Override public String execute() throws Exception { if (info.getUname().length()==0){ addFieldError("uname","用户名不能为空"); } if (info.getUpwd().length()==0){ addFieldError("upwd","密码不能为空"); } if(!info.getRepwd().equals(info.getUpwd())){ addFieldError("repwd","两次输入密码不一致"); } if(this.hasFieldErrors()){ return INPUT; } return SUCCESS; }
struts.xml配置
<!--使用execute()方法实现数据校验--> <action name="loginAction" class="cn.happy.action.LoginAction"> <result name="input">login.jsp</result> <result name="success">sucess.jsp</result> </action>
二.使用validate()实现数据校验
@Override public void validate() { if (info.getUname().length()==0){ addFieldError("uname","用户名不能为空"); } if (info.getUpwd().length()==0){ addFieldError("upwd","密码不能为空"); } if(!info.getRepwd().equals(info.getUpwd())){ addFieldError("repwd","两次输入密码不一致"); } }
struts.xml配置
<!--使用validate()实现数据校验--> <action name="loginAction" class="cn.happy.action.LoginAction"> <result name="input">login.jsp</result> <result name="success">sucess.jsp</result> </action>
三.使用validateXxx()方法实现数据校验
public void validateRegist(){ if(info.getUname().length()<6||info.getUname().length()>15){ addFieldError("uname","用户名长度在6-15位"); } if(info.getUpwd().length()<6){ addFieldError("upwd","密码要大于6位"); } } public String Regist(){ return SUCCESS; } public void validate() { if (info.getUname().length()==0){ addFieldError("uname","用户名不能为空"); } if (info.getUpwd().length()==0){ addFieldError("upwd","密码不能为空"); } if(!info.getRepwd().equals(info.getUpwd())){ addFieldError("repwd","两次输入密码不一致"); } }
struts.xml配置
配置action元素,指定Action由Regist()方法来进行请求的处理
<!--使用validateXxx()方法实现数据校验--> <action name="loginAction" class="cn.happy.action.LoginAction" method="Regist"> <result name="input">login.jsp</result> <result name="success">sucess.jsp</result> </action>
四.使用框架验证
已有的校验器
Struts 2.0已经为您实现很多常用的校验了,以下在jar的default.xml中的注册的校验器。
< validators > < validator name ="required" class ="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator" /> < validator name ="requiredstring" class ="com.opensymphony.xwork2.validator.validators.RequiredStringValidator" /> < validator name ="int" class ="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator" /> < validator name ="double" class ="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator" /> < validator name ="date" class ="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator" /> < validator name ="expression" class ="com.opensymphony.xwork2.validator.validators.ExpressionValidator" /> < validator name ="fieldexpression" class ="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator" /> < validator name ="email" class ="com.opensymphony.xwork2.validator.validators.EmailValidator" /> < validator name ="url" class ="com.opensymphony.xwork2.validator.validators.URLValidator" /> < validator name ="visitor" class ="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator" /> < validator name ="conversion" class ="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator" /> < validator name ="stringlength" class ="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator" /> < validator name ="regex" class ="com.opensymphony.xwork2.validator.validators.RegexFieldValidator" /> </ validators >
使用校验框架既可以方便地实现表单数据校验,又能够将校验与Action分离,故我们应该尽可能使用校验框架。
1编写验证文件,验证文件要和验证的Action放在同一个包下,并且采用ClassName-validation.xml方式命名,其中ClassName表示Action的类名
LoginAction-validation.xml编写
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> <validators> <!--用户名不能为空,长度在6-15位--> <field name="info.uname"> <field-validator type="requiredstring"> <param name="trim">true</param> <message>用户名不能为空</message> </field-validator> <field-validator type="stringlength"> <param name="maxLength">15</param> <param name="minLength">6</param> <message>用户名长度必须在${minLength}和${maxLength}之间</message> </field-validator> </field> <!--验证密码不为空,长度不小于6--> <field name="info.upwd"> <field-validator type="requiredstring"> <param name="trim">true</param> <message>密码不能为空</message> </field-validator> <field-validator type="stringlength"> <param name="minLength">6</param> <message>密码长度应大于等于${minLength}</message> </field-validator> </field> <!--验证确认密码--> <field name="info.repwd"> <field-validator type="fieldexpression"> <param name="expression">info.upwd==info.repwd</param> <message>两次输入密码要相同</message> </field-validator> </field> </validators>
struts.xml配置
<!--使用框架验证--> <action name="aaaaa" class="cn.happy.action.LoginAction" > <result name="input">login.jsp</result> <result name="success">sucess.jsp</result> </action>
上述的输出说明了Struts 2.0的数据校验工作方式,它需要经过下面几个步骤:
- 通过转换器将请求参数转换成相应的Bean属性;
- 判断转换过程是否出现异常。如果有,则将其保存到ActionContext中,conversionError拦截器再封装为fieldError;如果没有,进行下一步;
- 通过反射(Reflection)来调用validateXxx()方法(其中,Xxx表示Action的方法名);
- 调用validate()方法;
- 如果经过上述步骤没有出现fieldError,则调用Action方法;如果有,则会跳过Action方法,通过国际化将fieldError输出到页面。
不喜欢看文字的朋友,可以参考下面的图1。
看到这里可能大家会疑问:“这么多地方可以校验表单数据,到底我应该在那里做呢?”有选择是好事,但抉择的过程往往是痛苦的,往往让人不知所措。如果大家参照以下几点建议,相信会比较容易地做出正确的抉择。
- 如果需要转换的数据,通常做法在转换的时候做格式的校验,在Action中的校验方法中校验取值。假如用户填错了格式,我们可以通过在资源文件配置invalid.fieldvalue.xxx(xxx为属性名)来提示用户正确的格式,不同的阶段出错显示不同的信息。具体做法请参考上面的例子;
- 至于用validate()还是validateXxx(),我推荐使用validate()。原因是validateXxx()使用了反射,相对来说性能稍差,而validate()则是通过接口com.opensymphony.xwork2.Validateable调用。当然如果你的表单数据取值是取决于特定Action方法,则应该使用validateXxx()。