Struts2的输入校验

之前对请求参数的输入校验一般分为两部分:1.客户端校验,也就是我们写js代码去对客户的误操作进行过滤  2.服务端校验, 这是整个应用组织非法数据的最后防线.

Struts2的校验方式与其很大不同.Struts2是手动完成输入校验,可以编写自己的校验规则,基于Annotation的输入校验.

一.手工验证

比如说我们要验证如下: jsp界面用户输入的用户名不能为null,密码不能为null,且长度必须是6-12位.

那么在我们所的action中有两步是必须做的:1.action类必须继承ActionSuppprt 2.重写Validateable接口的validate()方法,在该方法中完成验证

过程如下:   validate()方法会在其他业务方法之前执行.

                  如果验证出错怎么办? 这就需要我们在struts.xml中配置出错转向的页面.

<result name="input">/validate/login.jsp</result>  其中input转向是在action中已经定义好的.public static final String INPUT = "input";

那什么时候才叫验证出错呢?有一个方法 this.addFieldError("sss","错误信息"):方法只向一个集合,当集合不为空的时候是验证出错.

, 如果系统的fieldErrors包含失败信息,Struts2会将请求转发名为input的result.在视图中通过<s:fieldError/>显示失败信息.

代码举例

public class RegistAction extends ActionSupport
{
//该请求包含的四个请求参数
private String name;
private String pass;
private int age;
private Date birth;
//name属性的setter和getter方法
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return (this.name);
}
//pass属性的setter和getter方法
public void setPass(String pass)
{
this.pass = pass;
}
public String getPass()
{
return (this.pass);
}
//age属性的setter和getter方法
public void setAge(int age)
{
this.age = age;
}
public int getAge()
{
return (this.age);
}
//birth属性的setter和getter方法
public void setBirth(Date birth)
{
this.birth = birth;
}
public Date getBirth()
{
return (this.birth);
}
//重写validate方法,进行数据校验
@Override
public void validate()
{
System.out.println("进入validate方法进行校验");
//如果用户名不为空,且不匹配长度为4~25的字母和数字组成的字符串。
if(name != null && !Pattern.matches("\\w{4,25}", name.trim()))
{
addFieldError("user" ,
"您输入用户名必须是字母和数字,且长度必须是4到25之间!");
}
//如果密码不为空,且不匹配长度为4~25的字母和数字组成的字符串。
if (pass != null && !Pattern.matches("\\w{4,25}", pass.trim()))
{
addFieldError("pass" ,
"您输入密码必须是字母和数字,且长度必须是4到25之间!");
}
//如果年龄不在有效的年龄段内
if (age > 150 || age <= 0)
{
addFieldError("age" , "您输入的年龄必须是一个有效的年龄!");
}
//取得有效生日的最后期限
Calendar end = Calendar.getInstance();
end.set(2050 , 2 , 21);
//取得有效生日的最早期限
Calendar start = Calendar.getInstance();
start.set(1900 , 1 , 1);
//如果生日不为空,且生日不是一个有效的生日。
if (birth != null && (birth.after(end.getTime()) || birth.before(start.getTime())))
{
addFieldError("birth" , "您输入的生日必须在一个有效的时间段内");
}
}
}

可见手工验证还是要写大量的代码,虽然相比servlet节省了类型转换,但是我们不想写代码~!所以我们一般会用配置文件的方式进行校验
二.基于XML配置方式实现输入校验

同上依然是对用户名不能为null,密码非空且长度在6-12位进行校验.

步骤: 1需要建立jsp页面

2.定义action  要注意action必须继承actionSupport或者实现Validateable接口

3.配置Struts_validate.xml文件 定义错误执行页面

         4. 该文件需要和action类放在同一个包下,配置验证文件的xml文件  文件命名格式为 ActionClassName-validation.xml ,  ActionClassName为简单类名

<validators>: 根元素
<field>:指定action中要校验的属性,name属性指定将被验证的表单字段的名字
<field-validator>:指定校验器, type 指定验证规则
上面指定的校验器requiredstring是由系统提供的,系统提供了能满足大部分验证需求
的校验器,这些校验器的定义可以在xwork-2.x.jar中的
com.opensymphony.xwork2.validator.validators下的default.xml中找到。
<param>:子元素可以向验证程序传递参数
<message>:子元素为校验失败后的提示信息,如果需要国际化,可以为message
指定key属性,key的值为属性文件中的key。

常见校验器

系统提供的校验器如下:
required (必填校验器,要求被校验的属性值不能为null)
requiredstring (必填字符串校验器,要求被校验的属性值不能为null,并且长度大于0,默认情况下会对字符串去前后空格)
stringlength(字符串长度校验器,要求被校验的属性值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格)
regex(正则表达式校验器,检查被校验的属性值是否匹配一个正则表达式,expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true)
int(整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值)
double(双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值)
fieldexpression(字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过)
email(邮件地址校验器,要求如果被校验的属性值非空,则必须是合法的邮件地址)
url(网址校验器,要求如果被校验的属性值非空,则必须是合法的url地址)
date(日期校验器,要求field的日期值必须在指定范围内,min指定最小值,max指定最大值)
conversion(转换校验器,指定在类型转换失败时,提示的错误信息)
visitor(用于校验action中复合类型的属性,它指定一个校验文件用于校验复合类型属性中的属性)
expression(OGNL表达式校验器,它是一个非字段校验器, expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过,该校验器不可用在字段校验器风格的配置中)

比如我们要对ValidateXmlAction类进行校验,xml应该是ValidateXmlAction-validation.xml

<?xml version="1.0" encoding="GBK"?>
<!-- 指定校验配置文件的DTD信息 -->
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.3//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
<!-- 校验文件的根元素 -->
<validators>
<!-- 校验Action的name属性 -->
<field name="name">
<!-- 指定name属性必须满足必填规则 -->
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>必须输入名字</message>
</field-validator>
<!-- 指定name属性必须匹配正则表达式 -->
<field-validator type="regex">
<param name="expression"><![CDATA[(\w{4,25})]]></param>
<message>您输入的用户名只能是字母和数字
,且长度必须在4到25之间</message>
</field-validator>
</field>
<!-- 校验Action的pass属性 -->
<field name="pass">
<!-- 指定pass属性必须满足必填规则 -->
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>必须输入密码</message>
</field-validator>
<!-- 指定pass属性必须满足匹配指定的正则表达式 -->
<field-validator type="regex">
<param name="expression"><![CDATA[(\w{4,25})]]></param>
<message>您输入的密码只能是字母和数字
,且长度必须在4到25之间</message>
</field-validator>
</field>
<!-- 指定age属性必须在指定范围内-->
<field name="age">
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>年纪必须在1到150之间</message>
</field-validator>
</field>
<!-- 指定birth属性必须在指定范围内-->
<field name="birth">
<field-validator type="date">
<!-- 下面指定日期字符串时,必须使用本Locale的日期格式 -->
<param name="min">1900-01-01</param>
<param name="max">2050-02-21</param>
<message>生日必须在${min}到${max}之间</message>
</field-validator>
</field>
</validators>

关系图如下:

检验器实例

//required  必填校验器
<field-validator type="required">
<message>性别不能为空!</message>
</field-validator> //requiredstring 必填字符串校验器
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空!</message>
</field-validator> //stringlength:字符串长度校验器
<field-validator type="stringlength">
<param name="maxLength">10</param>
<param name="minLength">2</param>
<param name="trim">true</param>
<message><![CDATA[产品名称应在2-10个字符之间]]></message>
</field-validator> //int:整数校验器
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>年龄必须在1-150之间</message>
</field-validator> //date: 日期校验器
<field-validator type="date">
<param name="min">1900-01-01</param>
<param name="max">2050-02-21</param>
<message>生日必须在${min}到${max}之间</message>
</field-validator> //url: 网络路径校验器
<field-validator type="url">
<message>传智播客的主页地址必须是一个有效网址</message>
</field-validator> //email:邮件地址校验器
<field-validator type="email">
<message>电子邮件地址无效</message>
</field-validator> //regex:正则表达式校验器
<field-validator type="regex">
<param name="expression"><![CDATA[^13\d{9}$]]></param>
<message>手机号格式不正确!</message>
</field-validator> //fieldexpression : 字段表达式校验
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[(password==repassword)]]></param>
<message>两次密码输入不一致</message>
</field-validator>

指定action方法的XML配置方式
当校验文件的取名为ActionClassName-validation.xml时,会对 action中的所有处理方法实施输入验证。

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

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

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

public String add() throws Exception{
....
}
public String update() throws Exception{
....
}

要对add()方法实施验证,校验文件的取名为: UserAction-user_add-validation.xml

要对update()方法实施验证,校验文件的取名为: UserAction-user_update-validation.xml

基于XML校验的一些特点

当为某个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的配置如下:

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

  .....

</action>

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

自定义验证规则

  • 自定义验证程序必须实现Validator接口
  •  Validation 拦截器负责加载和执行各种验证程序. 在加载了一个验证程序之后, 这个拦截器将调用那个验证程序的 setValidatorContext 方法, 把当前的 ValidatorContext 对象传递给它, 这使程序员可以访问当前 Action. 接下来, Validation 拦截器将调用 validate 方法并把需要验证的对象传递给它. validate 方法是编写一个自定义的验证程序时需要覆盖的方法.
  • ValidatorSupport 和 FieldValidatorSupport 实现了 Validator 接口     1.若需要普通的验证程序, 可以继承 ValidatorSupport 类 2.若需要字段验证程序, 可以继承 FieldValidatorSupport 类  3.若验证程序需要接受一个输入参数, 需要为这个参数增加一个相应的属性
  • 注册验证程序: 自定义验证器需要在类路径里的某个
    validators.xml 文件里注册:验证框架首先在根目录src下找validators.xml文件,没找到validators.xml文件, 验证框架将调用默认的验证设置,即default.xml里面的配置信息.
  • 位于com.opensymphony.xwork2.validator.validators 包下

举例:自定义一个 age 的验证器, 使 age 不能小于 0

1 首先在jsp界面增加一个组件     <s:textfield name="age" />

2 在action中增加private Integer age属性

3 自定义验证规则

public class AgeValidate extends FieldValidatorSupport {
/**
* object 表示当前执行的action对象
* object cn.itcast.validate.ValidateXmlAction@12dcb8c
*/
public void validate(Object object) throws ValidationException {
System.out.println("object "+object);
//获取字段的名称 age
String fieldName=this.getFieldName();
//获取字段的值
Object fieldValue=this.getFieldValue(fieldName, object);
System.out.println(fieldName +" "+fieldValue);
if(fieldValue instanceof Integer){
Integer age=(Integer)fieldValue;
if(age<0){
this.addFieldError(fieldName, object);
} }}}

4 在工程的src下新建validators.xml文件,在文件中增加如下内容   该xml文件采用的规范在xwork-core-2.1.6.jar包下的xwork-validator-config-1.0.dtd

5 在ValidateXmlAction-validation.xml文件中增加如下内容

最新文章

  1. Openfire 集群部署和负载均衡方案
  2. asp.net MVC中获取当前URL/Controller/Action
  3. 点击自动显示/隐藏DIV代码。(简单实用)
  4. [ExtJS5学习笔记]第十节 Extjs5新增特性之ViewModel和DataBinding
  5. 【HDOJ】3275 Light
  6. Javascript中null值,特别注意的两点
  7. LVS负载均衡中arp_ignore和arp_annonuce参数配置的含义
  8. C语言中复数运算及调用blas,lapack中复数函数进行科学计算
  9. Tcl与Design Compiler (五)——综合库(时序库)和DC的设计对象
  10. python变量、条件循环语句
  11. 【从零开始自制CPU之学习篇00】开篇
  12. Python-接口自动化(八)
  13. 关于新学期Python的一点见解
  14. script标签加载顺序(defer &amp; async)
  15. UGUI之不规则按钮的响应区域
  16. Android 本地搭建Tomcat服务器供真机测试
  17. collections模块(收藏)
  18. 打印时报emSize必须大于0
  19. 使用VS Code开发.Net Core 2.0 MVC Web应用程序教程之三(配置文件读取)
  20. 洛谷 P1992 不想兜圈的老爷爷 题解

热门文章

  1. 03.javabean
  2. AutoMapper IIS回收引发的 未将对象引用设置到对象实例
  3. WPF 简易的喷泉效果
  4. python学习总结笔记(一)
  5. mac 安装protobuf,并编译
  6. HTML5原生拖拽/拖放⎡Drag &amp; Drop⎦详解
  7. SpringMVC RequestMapping 详解
  8. Iptables详解七层过滤
  9. 《java.util.concurrent 包源码阅读》20 DelayQueue
  10. thinkphp系列:类的自动加载是如何设计的