零基础学Struts
上QQ阅读APP看书,第一时间看更新

5.1 Struts 2校验框架初探

5.1.1 使用校验框架的好处

前面介绍了Struts 2的输入校验,但是发现要实现输入校验就要编写大量的代码,而且修改起来比较麻烦。还有日期校验、邮箱校验,这些都是经常要用到输入校验,每次都需要手动地在validate()方法中来添加校验规则。

前面介绍的是在没有使用验证框架的基础上,全手动来添加输入校验功能。Struts 2框架是非常强大的,它提供了一套验证框架,通过验证框架能够非常简单和快速地完成输入校验。

基本的输入校验一定要熟悉。只有在了解了手动添加输入校验的基础上才能更好地了解Struts 2校验框架。这就是为什么一开始没有直接介绍使用Struts 2校验框架,而是介绍最基础的手动添加校验功能的原因。下面先回顾一下前面的校验代码,代码如下所示。

        public void validate() {
              //判断用户名是否输入,如果输入了,再判断格式是否正确
              if(username == null —— "".equals(username.trim())){
                    this.addFieldError("username", "用户名必须输入");
              } else if ( ! Pattern.matches("\\w{6,20}", username.trim())) {
                    this.addFieldError("username", "用户名必须是字母和数字,长度为620之间");
              }
              //判断密码是否输入,如果输入了,再判断格式是否正确
              if( password == null —— "".equals(password.trim())){
                    this.addFieldError("password", "密码必须输入");
              }else if( ! Pattern.matches("\\w{6,20}", password.trim())) {
                    this.addFieldError("password", "密码必须是字母和数字,长度为620之间");
              }
              //判断确认密码是否输入,如果输入了,再判断格式是否正确
              if(repassword == null —— "".equals(repassword.trim())){
                    this.addFieldError("repassword", "确认密码必须输入");
              }else if( ! Pattern.matches("\\w{6,20}", repassword.trim())) {
                    this.addFieldError("repassword", "确认密码必须是字母和数字,长度为620之间");
              }
              //判断确认密码和密码是否相同
              if(password ! = null && repassword ! = null && ! repassword.equals(password)){
                    this.addFieldError("repassword", "确认密码和密码必须相同");
              }
              //判断年龄是否合法
              if(age < 0 —— age >130) {
                    this.addFieldError("age", "请输入有效的年龄");
              }
              //判断出生日期是否合法
              Calendar start = Calendar.getInstance();
              Calendar end = Calendar.getInstance();
              start.set(1900, 1,1);
              end.set(2010, 1,1);
              if(birth ! = null && ( birth.after(end.getTime()) —— birth.
                      before(start.getTime()))) {
                      this.addFieldError("birth", "请输入有效的出生日期");
              }
              //判断邮箱地址是否合法
              if(email ! = null && ! "".equals(email) && email ! = "" && ! Pattern.matches("[a-zA-Z]
                    [a-zA-Z0-9._-]*@([a-zA-Z0-9-_]+\\.)+(com—gov—net—com\\.cn—edu\\.cn)", email)){
                    this.addFieldError("email", "请输入正确的邮箱地址");
              }
        }

通过在Action的validate()方法中添加校验代码来完成输入校验的。很显然,这样的校验方式编写起来比较繁琐,而且代码复用性不高。

假如添加一个用户表单,那么在对应的Action中的validate()方法中就必须添加相应的校验代码。但是很多校验规则都是相同的,所以就需要进行大量的复制粘贴的工作。

使用Struts 2提供的校验框架来实现输入校验能够大大减少代码编写时间,而且复用性非常好。编写起来非常简单,只需要添加一份xml格式的校验规则文件,代码如下所示。

        <? xml version="1.0" encoding="UTF-8"? >
        <! DOCTYPE validators PUBLIC
                "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
                "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
        <validators>
              <! --校验username 属性-->
              <field name="username">
                      <! --username必须输入 -->
                      <field-validator type="requiredstring">
                            <param name="trim">true</param>
                            <message>必须输入用户名</message>
                      </field-validator>
                      <! --username长度必须620之间,而且只能是数字和字母-->
                      <field-validator type="regex">
                              <param name="expression"><! [CDATA[(\w{6,20})]]></param>
                  <message>用户名长度必须为620之间</message>
              </field-validator>
      </field>
      <! --校验password属性-->
      <field name="password">
              <! --password必须输入 -->
              <field-validator type="requiredstring">
                  <param name="trim">true</param>
                  <message>必须输入密码</message>
              </field-validator>
              <! --password长度必须620之间,而且只能是数字和字母-->
              <field-validator type="regex">
                  <param name="expression"><! [CDATA[(\w{6,20})]]></param>
                  <message>密码长度必须为620之间</message>
              </field-validator>
      </field>
      <! --校验repassword属性 -->
      <field name="repassword">
              <! -repassword必须输入 -->
              <field-validator type="requiredstring">
                    <param name="trim">true</param>
                    <message>必须输入确认密码</message>
              </field-validator>
              <! -repassword长度必须620之间,而且只能是数字和字母-->
              <field-validator type="regex">
                    <param name="expression"><! [CDATA[(\w{6,20})]]></param>
                    <message>确认密码长度必须为620之间</message>
              </field-validator>
              <! -repassword的值必须和password的值相同 -->
              <field-validator type="fieldexpression">
                    <param name="expression"><! [CDATA[(repassword==password)]]></param>
                    <message>密码和确认密码必须一致</message>
              </field-validator>
      </field>
      <! --指定age值合法范围-->
      <field name="age">
          <field-validator type="int">
                  <param name="min">1</param>
                  <param name="max">120</param>
                  <message>年龄必须在${min}${max}之间</message>
          </field-validator>
      </field>
      <! --指定birth值合法范围-->
      <field name="birth">
          <field-validator type="date">
                  <param name="min">1900-01-01</param>
                  <param name="max">2010-01-01</param>
                  <message>出生日期必须在1900-01-012010-01-01之间</message>
          </field-validator>
                </field>
                <! --校验email属性-->
                <field name="email">
                    <field-validator type="email">
                            <message>请输入有效的电子邮箱地址</message>
                    </field-validator>
                </field>
          </validators>

通过这个规则文件与以前手动添加的校验代码所实现的输入校验功能完全相同。

从表面上看代码确实多了,可能觉得越来越复杂了。其实不然,注意观察这个规则文件,大部分的都是一些标签。只需要在这些标签中添加相应的参数就可以完成校验功能,而不用手动添加代码来判断用户输入的信息。下面来看如何来编写该文件。

5.1.2 编写校验规则文件

前面提到的校验规则文件其实就是一个XML文件。该规则文件名为“ActionName-validation.xml”。其中ActionName为对应处理Action的类名,“-validation.xml”为固定格式。文件存放在Action文件的相同目录下。现在有一个问题,如何查看这个XML文件中有哪些标签呢?

首先可以查看该XML文件中的声明,从而知道该XML文件必须符合什么规范。比如上面这个文件就必须符合“http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd”中定义的语法规则。通过上面的链接下载“xwork-validator-1.0.2.dtd”文件并打开该文件,代码如下所示。

        <? xml version="1.0" encoding="UTF-8"? >
        <! --
          XWork Validators DTD.
          Used the following DOCTYPE.
          <! DOCTYPE validators PUBLIC
                    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
                    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
        -->
        <! ELEMENT validators (field—validator)+>
        <! ELEMENT field (field-validator+)>
        <! ATTLIST field
            name CDATA #REQUIRED
        >
        <! ELEMENT field-validator (param*, message)>
        <! ATTLIST field-validator
            type CDATA #REQUIRED
            short-circuit (true—false) "false"
        >
        <! ELEMENT validator (param*, message)>
        <! ATTLIST validator
            type CDATA #REQUIRED
            short-circuit (true—false) "false"
        >
        <! ELEMENT param (#PCDATA)>
        <! ATTLIST param
            name CDATA #REQUIRED
        >
        <! ELEMENT message (#PCDATA)>
        <! ATTLIST message
            key CDATA #IMPLIED
        >

下面逐步来分析该DTD文件。

下面代码表示校验规则文件的根元素为validators。根元素下包括field元素或者validator元素。这两个元素可以出现一次或者多次。

        <! ELEMENT validators (field—validator)+>

下面代码表示field元素包含一个或者多个field-validator元素。同时field元素包含一个属性name,值为字符数据(character data), name属性是必须给定的。

        <! ELEMENT field (field-validator+)>
        <! ATTLIST field
            name CDATA #REQUIRED
        >

下面代码表示field-validator元素包含0个或者多个param元素,同时包含一个message元素。field-validator元素包含一个type属性,值为字符数据(character data),该属性是必须给定的。field-validator元素还包含一个可选的属性short-circuit,其值为true或者false中的一个,默认情况下为false。

        <! ELEMENT field-validator (param*, message)>
        <! ATTLIST field-validator
            type CDATA #REQUIRED
            short-circuit (true—false) "false"
        >

下面代码表示validators元素中包含0个或者多个param元素,包含一个message元素。validator元素包含一个type属性,值为字符数据(character data),该属性是必须给定的。validator元素还包含一个可选的属性short-circuit,其值为true或者false中的一个,默认情况下为false。

        <! ELEMENT validator (param*, message)>
        <! ATTLIST validator
            type CDATA #REQUIRED
            short-circuit (true—false) "false"
        >

下面代码表示param元素中包含一个属性name,值为字符数据(character data),该属性是必须给定的。

        <! ELEMENT param (#PCDATA)>
        <! ATTLIST param
              name CDATA #REQUIRED
        >

下面代码表示message元素中包含一个属性key,值为字符数据(character data),该属性是可选的。

        <! ELEMENT message (#PCDATA)>
        <! ATTLIST message
            key CDATA #IMPLIED

通过上面的DTD规范,可以设计校验规则文件代码如下。

        <? xml version="1.0" encoding="UTF-8"? >
          <! DOCTYPE validators PUBLIC
                "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
                "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
        <validators>
              <field name="">
                    <field-validator type="">
                            <param name=""></param>
                            <param name=""></param>
                            <message key=""></message>
                    </field-validator>
            </field>
            <validator type="">
                    <param name=""></param>
                    <param name=""></param>
                    <message key=""></message>
            </validator>
        </validators>