客户端校验进行基本校验,如检验非空字段是否为空,数字格式是否正确等。客户端校验主要用来过滤用户的误操作。作用是:拒绝误操作输入提交到服务器处理,降低服务器端负担。
服务器端校验也必不可少,服务器端校验防止非法数据进去程序,导致程序异常,底层数据库异常。服务器端校验是保证程序有效进行及数据完整的手段。
对异常输入的过滤,就是输入校验,也称为数据校验
输入校验分为客户端校验和服务器校验:
1. 客户端校验主要是过滤正常用户的误操作,主要通过js代码完成。
2. 服务器端校验是整个应用阻止非法数据的最后防线,主要通过在应用中编程实现。
1.编写校验文件
struts2提供了基于验证框架的输入校验,使用其进行校验时无须对程序代码进行任何改变,只需编写校验规则文件即可。
registForm.jsp
<s:form action ="regist">
<s:textfield name="name" label="用户名"/>
<s:textfield name="pass" label="密码"/>
<s:textfield name="age" label="年龄"/>
<s:textfield name="birth" label="生日"/>
</s:form>
RegistAction.java
public class RegistAction extends ActionSupport{
private String name;
private String pass;
private int age;
private Date birth;
set,get方法
public String execute() throws Exception{
return SUCCESS;
}
}
RegistAction-validation.xml
<field-validator.../>是字段校验器的配置风格,而<validator.../>是非字段校验器的配置风格。
<validators>
<field name="name">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>必须输入名字</message>
</field-validator>
<field-validator type="regex">
<param name="regex"><![CDATA[(\w{4,25})]]></param>
<message>您输入的用户名只能是字母和数字,且长度必须在4到25之间</message>
</field-validator>
</field>
<field name="pass">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>必须输入密码</message>
</field-validator>
<field-validator type="regex">
<param name="regex"><![CDATA[(\w{4,25})]]></param>
<message>您输入的密码只能是字母和数字,且长度必须在4到25之间</message>
</field-validator>
</field>
<field name="age">
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>年级必须在1-150之间</message>
</field-validator>
</field>
<field name="birth">
<field-validator type="date">
<param name="min">1900-01-01</param>
<param name="max">2050-02-21</param>
<message>生日必须在${min}到${max}之间</message>
</field-validator>
</field>
</validators>
struts2中每个Action都有一个校验文件,因此该文件名应该遵循如下规则:
<Action名字>-validator.xml
该文件被保存在与Action class文件相同的路径下。与类型转换失败相似的是,当输入校验失败后,sruts2也是自动返回名为”input”的Result,因此需要在struts.xml文件中配置名为”input”的Result
<action name="regist" class="">
<result name="input">/WEB-INF/content/</result>
<result>/WEB-INF/content</result>
</action>
校验失败后可以在input逻辑视图名的物理视图中添加<s:fielderror/>
来输出错误提示。
类型转换失败的提示信息,输入校验失败的提示信息都被封装成FieldError,并被放入Action Context中,而且校验失败时都将返回input逻辑视图名,且都是用<s:fielderror/>
标签来输出错误提示信息
2.国际化提示信息
每个校验文件中每个<field-validator.../>
元素都包含一个必填的<message.../>
子元素,这个子元素中的内容就是校验失败后的提示信息。为了国际化提示信息,为message元素指定key属性,该key属性指定是国际化提示信息对应的key。
RegistAction-validator.xml
<validators>
<field name="age">
<field-validator>
<param name="min">1</param>
<param name="max">150</param>
<message key="age.range"/>
</field-validator>
</field>
</validators>
RegistAction.properties
#违反年龄必须在指定范围的提示信息
age.range=您的年龄必须在${min}和${max}之间
3.使用客户端校验
在struts2中使用客户端校验,只需修改两处:
- 将输入页面的表单元素改为使用struts2标签来生成表单。
- 为该<s:form.../>
元素增加validate=”true”属性,该表单就具有了客户端校验功能。
修改上面的表单元素:
<s:fielderror/>
<s:form action ="regist" validate="true">
<s:textfield name="name" label="用户名"/>
<s:textfield name="pass" label="密码"/>
<s:textfield name="age" label="年龄"/>
<s:textfield name="birth" label="生日"/>
</s:form>
该页面的地址依然停留在原来的页面,并未提交到对应的Action,这就表明:上面的数据校验过程是客户端完成的。
客户端校验值得注意的地方:
1. struts2的<s:form.../>
元素有一个theme属性,不要将该属性指定为simple。
2. 浏览者不能直接访问启用客户端校验的表单页,这样会引发异常。可以把启用客户端校验的表单页放到WEB-INF路径下,让浏览者访问所有资源之前都先经过它的核心Filter。
3. 如何客户端校验希望输出国际化提示信息,那就需要使用全局国际化资源文件,不能使用Action范围的国际化资源文件。
4. 启用客户端校验的表单页面的action和namespace要分开写,例如向namespace为/lee,name为registe的Action请求,应写成<s:form action="regist" namespace="/lee">
而不应该写成<s:form action="lee/regist">
一旦使用了MVC框架,就该严格遵守MVC思想,应该尽量避免让浏览者直接访问Web应用的视图页面,而应该让浏览者向控制器发送请求,有控制器调用页面向浏览者呈现数据。
4.字段校验器配置风格
- 字段优先,称为字段校验器风格
- 校验器优先,称为非字段校验器风格
使用字段校验器配置风格时,每个字段校验规则遵循如下:
<field name="被校验的字段">
<field-validator type="校验器名">
<!-- 此处需要为不同校验器指定数量不等的校验参数-->
<param name="参数名">参数值</param>
...
<!-- 校验失败后的提示信息,其中key指定国际化的key-->
<message key="Il8Nkey">校验失败后的提示信息</message>
</field-validator>
</field>
<field.../>
元素是校验规则文件的基本组成单位。
5.非字段校验器配置风格
<validators>
<validator type="校验器名">
<param name="fieldName">需要被校验的字段</param>
<!-- 此处需要为不同校验器指定数量不等的校验参数-->
<param name="参数名">参数值</param>
...
<!-- 校验失败后的提示信息,其中key指定国际化的key-->
<message key="Il8Nkey">校验失败后的提示信息</message>
</validator>
</validators>
必须为
6.短路校验器
校验规则文件的<validator.../>
元素和<field-validator../>
元素可以指定一个可选的short-circuit属性,这个属性指定校验器是否是短路校验器,该属性的默认值为false,即默认是非短路校验器。
短路校验器的效果:浏览者完全没有为某个输入框输入任何内容,系统应该仅输入第一行提示信息,而不是一次性输出所有的校验提示。
<validators>
<field name="name">
<field-validator type="requiredstring" short-circuit="true">
<param name="trim">true</param>
<message>必须输入名字</message>
</field-validator>
<field-validator type="regex">
<param name="regex"><![CDATA[(\w{4,25})]]></param>
<message>您输入的用户名只能是字母和数字,且长度必须在4到25之间</message>
</field-validator>
</field>
</validators>
对于同一个字段内的多个校验器,如果一个短路校验器校验失败,其他校验器都根本不会继续校验。
7.校验文件的搜索规则
struts2的一个Action中可能包含了多个处理逻辑,每个方法都是一个处理逻辑。不同的处理逻辑可能需要不同的校验规则,struts2允许为不同控制逻辑指定不同校验规则的文件。
当需要让一个Action可以处理多个请求时,应该在配置该Action是指定method属性,就可以将一个Action处理类配置成多个逻辑。
struts.xml
<action name="*Pro" class="" method="{1}">
<result name="input">/WEB-INF/content/</result>
<result>/WEB-INF/content/</result>
</action>
为了能精确控制每个校验逻辑,struts2允许通过为校验规则文件名增加Action别名来指定具体需要校验的处理逻辑。
<ActionClassName>-<ActionAliasName>-validation.xml
RegistAction-loginPro-validation.xml
假设系统有两个Action:BaseAction和RegistAction,其中RegistAction继承了BaseAction,则系统搜索规则文件顺序如下:
1. BaseAction-validation.xml
2. BaseAction-别名-validation.xml
3. RegistAction-validation.xml
4. RegistAction-别名-validation.xml
即使找到一个校验规则,系统还会继续搜索,不管有没有这4份文件,也不管是否找到配置文件,系统总是按固定顺序搜索。
8.检验顺序和短路
校验器的执行顺序有如下原则:
- 所有非字段风格的校验器优先于字段风格的校验器。
- 所有非字段风格的校验器中,排在前面的会执行。
- 所有字段风格的校验器中,排在前面的会先执行。
校验器短路的原则如下:
1. 所有非字段校验器是最优先执行,如果某个非字段校验器校验失败了,则该字段上所有字段校验器都不会获得校验的机会。
2. 非字段校验器的校验失败,不会阻止其他非字段校验的执行。
3. 如果一个字段校验器校验失败后,则该字段下且排在该校验失败的校验器之后的其他字段校验器不会获得校验的机会。
4. 字段校验器永远都不会阻止非字段校验器的执行
9.内建校验器
xwork-2.3.16.3.jar文件中com\opensymphony\xwork2\validator\validators路径下找到default.xml文件中就是默认的校验器注册文件。
1.必填校验器(required)
该校验器要求指定的字段必须有值(非空)
参数为:
- fieldName:该参数指定校验的Action属性名。如果采用字段校验风格则不需自定该参数。
2.必填字符串校验器(requiredstring)
该校验器要求字段值必须非空且长度大于0,即该字符串不能是”“。
参数为:
- fieldName: 该参数指定校验的Action属性名。
- trim:是否在检验前截断被校验属性值前后的空白。该属性是可选的
3.整数校验器(int、long、short)
该校验器要求字段的整数值必须在指定范围内。
参数为:
- fieldName:该参数指定校验的Action属性名。
- min:指定该属性的最小值。
- max:指定该属性的最大值。
4.日期校验器(date)
该校验器要求字段的日期值必须在指定范围内。
参数:
- fieldName:该参数指定校验的Action属性名。
- min:指定该属性的最小值。
- max:指定该属性的最大值。
5.表达式校验器(expression)
它是一个非字段校验器,不可在字段校验器的配置风格中使用。该表达式校验器要求OGNL表达式返回true,当返回true时,该校验通过。
参数:
- expression:该参数指定一个逻辑表达式,该逻辑表达式基于ValueStack进行求值,最后返回一个Boolean值。
6.字段表达式校验器(fieldexpression)
要求指定字段满足一个逻辑表达式。
参数:
- fieldName:该参数指定校验的Action属性。
- expression:该参数指定一个逻辑表达式,该逻辑表达式基于ValueStack进行求值,最后返回一个Boolean值。
7.邮件地址校验器(email)
要求被检查字段的字符如果非空,则必须是合法的邮件。不过这个校验器其实就是基于正则表达式进行检查的。
参数:
- fieldName:该参数指定校验的Action属性名。
8.网址校验器(url)
要求被检查字段的字符如果非空,则必须是合法的URL地址。
参数:
- fieldName:该参数指定校验的Action属性名。
9.Visitor校验器
主要用于检测Action里的复合属性,例如一个Action里包含了User类型的属性。
public class RegistAction extends ActionSupport{
private User user;
set,get方法
}
public class User{
private String name;
private String pass;
set,get 方法
}
RegistAction-validation.xml
<validators>
<field name="user">
<field-validator type=""visitor>
<param name="context">userContext</param>
<!-- 指定校验失败后提示信息是否添加下面前缀-->
<param name="appendPrdfix">true</param>
<message>用户的:</message>
</field-validator>
</field>
</validators>
User-userContext-validator.xml
<validators>
<field name="name">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message key="name.required"/>
</field-validator>
<field-validator type="regex">
<param name="regex"><![CDATA[(\w{4,25})]]></param>
<message>您输入的用户名只能是字母和数字,且长度必须在4到25之间</message>
</field-validator>
</field>
</validators>
JSP页面
<s:form action="regist">
<s:textfield name="user.name" label="用户名"/>
</s:form>
user.name 这个属性表示直接绑定到Action实例的user属性的name属性
10.转换校验器(conversion)
检查被校验字段在类型转换过程中是否出现错误。
参数:
- fieldName:该参数指定校验的Action属性。
- repopulateField:该参数指定当类型转换失败后,返回input页面是,类型转换失败的表单域是否保留原来的错误输入。
11.字符串长度校验器(stringlength)
要求被校验字段的长度必须在指定的范围之内,否则就算校验失败。
参数:
- fieldName:该参数指定校验的Action属性名。
- maxLength:该参数指定字段值的最大值。
- minLength:该参数指定字段值得最小值。
- trim:指定校验该字段之前是否截断该字段前后的空白。
12.正则表达式(regex)
检查被校验字段是否匹配一个正则表达式。
参数:
- fieldName:该参数指定校验的Action属性名。
- regex:指定匹配用的正则表达式。
- caseSensitive:该参数指明进行正则表达式匹配时,是否区分大小写。
10.基于注解的输入校验
是由XWork框架提供的。
使用验证器注解修饰Action里各成员变量对应的setter方法即可。
public class RegistAction extends ActionSupport{
private String name;
@RequiredStringValidator(key="name.required",message="")
@RegexFieldValidator(regex="\\w{4,25}",key="name.regex",message="")
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
11.手动完成输入校验
1. 重写validate()方法
public class RegistAction extends ActionSupport{
private String name;
private String pass;
private int age;
privare Date birth;
set,get方法
public void validate(){
System.out.println("进入validate方法进行校验" + name);
if(!name.contains("crazyit")){
addFieldError("user","您的用户名必须包含crazyit!");
}
}
}
ActionSupport类里包含了一个getText()方法,该方法可用于取得国际化信息。
- 重写validateXxx()方法
为了实现校验指定处理逻辑的功能,struts2的Action允许提供一个validateXxx()方法,其中xxx即是Action对应的处理逻辑方法。
public class RegistAction extends ActionSupport{
private String name;
private String pass;
private int age;
privare Date birth;
set,get方法
public void validateRegist(){
System.out.println("进入validate方法进行校验" + name);
if(!name.contains("crazyit")){
addFieldError("user","您的用户名必须包含crazyit!");
}
}
}
struts.xml
<action name="regist" class="" method="regist">
</action>
浏览者向regist提交请求,该请求将由RegistAction的regist()处理逻辑处理,那么不仅validate()方法会进行输入校验,validateRegist()方法也会执行输入校验,而validateRegist()方法先调用。
struts2输入校验需要经过如下几个步骤
- 类型转换器负责对字符串的请求参数执行类型转换,并将这些值设置成Action的属性值。
- 在执行类型转换过程中可能出现异常,如果出现异常,将异常信息保存到ActionContext中,conversionError拦截器负责将其封装发哦FieldError里,然后执行下一步,如果没有异常,直接进行下一步。
- 使用strurs2应用中所配置的校验器进行输入校验。
- 通过反射调用validateXxx()方法。
- 调用Action类里的validate()方法。
- 如果经过上面都没有出现FieldError,将调用Action里处理用户请求的处理方法;如果出现了,系统将转入input逻辑视图所指定的视图资源。