Struts2 输入校验

19 篇文章 0 订阅
7 篇文章 0 订阅

为什么要有输入校验

输入校验也是所有Web应用必须处理的问题,因为Web应用的开放性, 网络上所有的浏览者都可以自由使用该应用,因此该应用通过输入页面收集的数据是非常复杂的,不仅会包含正常用户的误输入,还可能包含恶意用户的恶意输入。一个健壮的应用系统必须将这些非法输入阻止在应用之外,防止这些非法输入进入系统,这样才可以保证系统不受影响。

异常的输入,轻则导致系统非正常中断,重则导致系统崩溃。应用程序必须能正常处理表现层接收的各种数据,通常的做法是遇到异常输入时应用程序直接返回,提示浏览者必须重新输入,也就是将那些异常输入过滤掉。对异常输入的过滤,就是输入校验, 也称为数据校验。

输入校验分为客户端校验和服务器校验,客户端校验主要是过滤正常用户的误操作,主要通过JavaScript代码完成;服务器端校验是整个应用阻止非法数据的最后防线,主要通过在应用中编程实现。

客户端校验的主要作用是防止正常浏览者的误输入,仅能对输入进行初步过滤;对于恶意用户的恶意行为,客户端校验将无能为力。因此,客户端校验绝不可代替服务器端校验。当然,客户端校验也绝不可少,因为Web应用大部分浏览者都是正常的浏览者,他们的输入可能包含了大量的误输入,客户端校验把这些误输入阻止在客户端,从而降低了服务器的负载。(如果你都把数据放在服务端校验,这些错误的数据会在网络传输,浪费带宽,你觉得合适吗?)

Struts 2的输入校验既包括服务器端校验,也包括客户端校验。

编写检验规则文件

校验文件就是每一个表单域要满足的条件。

这里我们需要注意的就是,我们表单校验是基于你输入表单数据类型要正确那个转换。

  <s:form action="login"  method="get">
  <s:textfield name="name" label="姓名"/>
  <s:textfield name="pass" label="密码"/>
  <s:textfield name="age" label="年纪"/>
  <s:textfield name="birth" label="生日"/>
  <s:submit value="注册"/>
  </s:form>

Action 就是提供表单属性的set、get方法。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC 
    "-//Apache Struts//XWork Validator 1.0.3//EN"
    "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<!-- 校验文件的根元素 -->
<validators>
<field name="name">
    <field-validator type="requiredstring">
         <param name="trim">true</param>
         <message>名称必须填</message>
    </field-validator>
    <field-validator type="regex">
        <param name="regexExpression">![CDATA[(\w{4,25})]]</param><!--regex,regexExpression name是这两种类型都可以 -->
        <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">2020-09-09</param>
        <message>时间不能超过规定的日期哦</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>
</validators> 


我这里写的类型器,就这几个,至于其他的,自己需要的时候自己百度。

编写校验规则文件注意点:

<!DOCTYPE validators PUBLIC 
    "-//Apache Struts//XWork Validator 1.0.3//EN"
    "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">

这段话是引入校验器的环境,没有这个,首先标签就不能自动提示。你可以不能乱写,这里的版本号一定要对应你的xworkjar包下面的,校验器配置文件,这里才可以哦。具体,你可以自己解压jar包,支持哪个版本。

这里也提醒了大家,大家在使用框架的配置文件的时候,在导入环境的时候,你最好自己看看它是怎么引用,以免版本问题。

  • 和类型转换一样,校验失败的时候,会返回input视图,所以,你需要配置一个input视图。
  • 查看校验失败信息的时候,你需要来显示。
配置国际化资源

国际化资源讲解

国际化资源文件存放在src下。

在上述的代码:做如下的修改

<field-validator type="requiredstring">
         <param name="trim">true</param>
         <message key="name.require"></message>
    </field-validator>

创建资源文件,具体可以参考上面链接

name.require=\u540D\u5B57\u5FC5\u987B\u7684
<constant name="struts.custom.i18n.resources" value="base" />

在struts中配置常量属性,上面链接中,如果是配置包的资源属性和action的资源属性文件是不需要配置该常量属性。

使用客户端校验

客户端的校验是基于JavaScript的。

在MVC的思想中,用户是不可以向视图,也就是Jsp发出请求,而是应该向控制器(action)发送请求,由控制器返回视图。

当我们请求jsp的时候,我们需要配置一个通用的action来返回jsp。

 <action name="*">
 <result >/{1}.jsp</result>
 </action>

这个表示什么意思,就是当我们在请求的时候,输入的action,*是匹配任意的,这时就是转到/你输入action名字.jsp。

至于校验文件,按照上面的,没有如何改变。

在表单form中添加该属性:

validate="true" 

注意运行之后,地址栏的变化。

这里写图片描述

地址栏没有变化,没有提交到对应的action中校验,这就是完成在客户端的校验。

客户端的校验实际上,减少不必要的带宽,你把错误数据传过去,是不是浪费带宽,如果说必须是服务器的检验,那是没办法。

客户端支持的校验器:

这里写图片描述

客户端校验的注意点:

  • Struts2的表单有一个theme属性,不要将该属性指定为simple。
  • 启用客户端校验的表单页面的action和namespace要分开写,例如我们向namespace 为/lee, name为registPro 的Action请求,应写成, 而不应该写成。一般不写namespace默认是在跟目录下。
字段校验器配置风格

字段是优先的。

之前的校验文件就是基于字段的,这里的例子,就不在演示,只是做些文字说明。

field元素是校验规则文件的基本组成单位,每个field元素指定一个Action属性必须遵守的规则,该元素的name属性指定了被校验的字段;如果该属性需要满足多个规则,则在该field元素下增加多个field-validator元素。

每个field-validator元素指定一个校验规则,该元素的type属性指定了校验器名称,该元素可以包含多个param子元素,用于指定该校验器的参数;除此之外,每个field-validator元素都有一个必需的message元素,该元素确定校验失败后的提示信息。

message元素的key属性指定了校验失败后提示因际化信息对应的key,该元素的内容是校验失败后的默认提示信息。

非字段校验器

校验器优先。

每个validator元素定义了一个校验规则,该元素需要-个type属性,该type属性指定了该校验器的名字。

使用非字段校验器的配置风格时,采用的是校验器优先的方式,故必须为validator配置一个fieldName参数,该参数的值就是被校验的Action属性名。除此之外,还需要指定数量不等的param元素,这些都是指定校验器所需的参数。

<validators>
<validator type="requiredstring">
<param name="fieldName">name</param>//这个是必须要有的
<param name="trim">true</param>
<message>名称必须有</message>
</validator>
</validators>

字段校验器和非字段校验器使用,主要看你喜欢哪一种。

短路校验器

短路这个概念,我相信大家应该都懂,一个不成功,后面的就不要判断,直接否定。

在刚才上面的校验器中,我们对于名字字段,我们设置了两个校验器,一个是必填字段,还有一个是用户名长度,校验的时候,你如果两个都不符合,它就会两个提示信息,这又必要吗,如果都不输入用户名,何来长度之说。

修改校验文件:

<field name="name">
    <field-validator type="requiredstring" short-circuit="true">
         <param name="trim">true</param>
         <message key="name.require"></message>
    </field-validator>
    <field-validator type="regex">
        <param name="regexExpression">![CDATA[(\w{4,25})]]</param>
        <message key="name.length"></message>
    </field-validator>
</field>

我们给用户名的必填字段设置了短路,也就是说如果你没有填用户名,其他校验器是不会起作用的。

字段的校验器的短路属性,默认是false。如果设置为true,一旦短路校验器不通过,后面的校验器是不会起作用的。

校验文件搜索规则

Struts2的一个Action中可能包含了多个处理逻辑,当一个Action类中包含多个类似于execute的方法时,每个方法都是一个处理逻辑。不同的处理逻辑可能需要不同的校验规则,Struts2 允许为不同控制逻辑指定不同校验规则的支持。

当需要让一个Action可以处理多个请求时,应该在配置该Action时指定method属性。通过这种方式,就可以将一个Action处理类配置成多个逻辑Action。

我们修改action,配置多个逻辑处理方法。

public String regist() throws Exception {
    // TODO Auto-generated method stub
    System.out.println(name+"jjjj");
    return SUCCESS;
}

public String login() throws Exception{
    return  SUCCESS;
}

你自己定义方法的时候,一定要删除重写的那个注解。

配置Strut配置文件:

<action name="*pro" class="com.example.test.action.LoginAction" method="{1}">

   <result name="input">/index.jsp</result>
    <result name="success">/show.jsp</result>
    <allowed-methods>login,regist</allowed-methods>
 </action>

这里你的action名称是loginpro,它就会对应的执行login方法。

但是这里有一个需要注意的地方,allowed-methods 这个标签,在struts 2.5的时候,必须要写这个,否则,它会报找不到对应的action。

修改jsp:

 <s:submit value="注册"  onclick="this.form.action='registpro';"/>
  <s:submit value="登录"  onclick="this.form.action='loginpro';"/>

两个按钮提交到不同的action。

我在登录,我们希望,判断它的用户名和密码是否一样。

<validators>
<field name="name">
    <field-validator type="fieldexpression">
        <param name="expression">![CDATA[(name==pass)]]</param>
        <message>用户名和密码不能相同</message>
    </field-validator>
</field>
</validators>
<ActionClassName>-<ActionAliasName> - validation.xml

其中ActionClassName是Action处理类的类名,而ActionAliasName 就是在struts.xml 中配置该Action时所指定的name属性。

基于上面上面的配置,我们就可以完成action多个处理方法的校验

<ActionClassName>-validation.xml
<ActionClassName>-<ActionAliasName> - validation.xml

这个两个校验文件,我们通过执行发现,ActionAliasName的action的校验规则是包含上面两个校验规则的。而如果不是ActionAliasName的action,则只会执行ActionClassName-validation.xml。在这里里面ActionClassName-validation.xml就像总的,所有人都要听,每个人都要执行的校验,只要是对应的是ActionClassName类,ActionClassNameActionAliasName-validation.xml,只是一个局部,就针对ActionAliasName action的校验。

注意点:

假设系统有两个Action: BaseAction 和RegistAction,则系统搜索规则文件顺序如下:

  • BaseAction-validation.xml
  • BaseAction-别名-validation.xml
  • RegistAction-validation.xml
  • RegistAction-别名-validation.xml

由上面可以看出,校验文件的搜索是一直进行的,只有有对应的校验文件,即使找到第一个校验文件,也还是会继续往下,直到结束。如果校验规则冲突,则搜索靠后的获胜。

校验顺序和短路

这里写图片描述

内建校验器

Struts2提供了大量的内建校验器,这些内建的校验器可以满足大部分应用的校验需求,开发者只需要使用这些校验器即可。如果应用有一个特别复杂的校验需求,而且该校验有很好的复用性,开发者可以开发自己的校验器。

你可以在xwork下的validators路径下找到一个default.xml文件,这个文件就是Struts2默认的校验器注册文件,包含了struts全部支持的校验器。

注册一个校验器是如此简单:通过一个validator元素即可注册一个校验器,每个validator元素的name属性指定该校验器的名字,class 属性指定该校验器的实现类。

如果开发者开发了一个自己的校验器,则可以通过添加一个validators.xml文件(该文件应该放在WEB-INF/classes路径下来注册校验器。validators.xml文件的内容也是由多个validator元素组成的,每个

  <s:form  action="login"   >
  <s:textfield name="user.name" label="姓名"/>
  <s:submit value="注册"  />
  </s:form>

在action中定义这个属性,是复合属性User类型,并且提供set、get方法。

    private User user;

定义action的校验文件

LoginAction-validation.xml

<field name="user">
<field-validator type="visitor">
<param name="context">usercontex</param>
<message>the name of user is error</message>
</field-validator>
</field>

这个校验文件只是指定user字段的校验方式,并没有指出User中name字段的校验规则,所以我们还是需要为User定义校验文件。

这个校验没啥难的,就是前面校验文件的name的校验,不过这个文件的名字因为是针对的是User,User-usercontex-validation.xml ,usercontex是上面参数的值。另外,还要注意的是该文件是针对User,应该和bean放在同一个包下

基于注解的输入校验

有jdk1.5之后2,支持注解,这真的是太方便了。

    @RequiredStringValidator(message="你的名字有误啦")

我们直接可以在对应的action文件中的属性的set方法上面,使用各种注解校验器。

在这里需要提醒大家的是,一旦使用注解校验,你原来的校验文件,就要删除,否则,它还是找到那个文件,以防带来错误。

在注解校验的几个属性中:

  • key 是指定国际资源文件的的键key,如果你指定key,就是代表错误信息使用的是国际资源文件的,message属性就不要填任何东西,但是必须要有message属性,它是api规定的。
  • 还有一个api规定的属性是type,该属性是说明,该校验器是非字段校验,还是字段校验,它默认是字段校验。

基于这种方式比较简单,但是它所有的代码都集中到了action的java中,还是有不好的地方。

手动完成校验

基于Struts的校验可以说,已经能够满足绝大多数的需求,但是这些校验器的逻辑是固定的,无法满足一些固定的需求。

重写action的validate方法
@Override
public void validate() {
    // TODO Auto-generated method stub
    super.validate();
}

在这个方法里面,你可以定义自己的校验逻辑。通过addFieldError()方法把错误信息添加到系统中,Struts发现系统FieldError不为空,就会转入input页面。

ValidateXxxx 方法

Struts 2的Action类里可以包含多个处理逻辑,不同的处理逻辑对应不同的方法。即Struts2的Action类里定义了几个类似于execute的方法, 只是方法名不是execute。

如果我们的输入校验只想校验某个处理逻辑,也就是仅校验某个处理方法,则重写validate 方法显然不够,validate方法无法准确知道需要校验哪个处理方法。实际上,如果我们重写了Action的validate 方法,则该方法会校验所有的处理逻辑。

为了实现校验指定处理逻辑的功能,Struts 2的Action允许提供一个validateXxx0方法,其中xxx即是Action对应的处理逻辑方法,首字母要大写。

下面给出了局部代码:

<action name="*pro" class="com.example.test.action.LoginAction" method="{1}">
   <result name="input">/index.jsp</result>
    <result name="success">/show.jsp</result>
    <allowed-methods>login,regist</allowed-methods>
 </action>
public void validateLogin() {
    // TODO Auto-generated method stub
    super.validate();
    if(name.contains("laoqiang")){
    addFieldError("user", "name is error"); 
    }

}

public void validateRegist() {
    // TODO Auto-generated method stub
    super.validate();
    if(name.contains("laoqiang")){
    addFieldError("user", "pass is error"); 
    }

}
Struts 2 数据校验的流程

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值