自己定义验证器——用Struts2框架以框架师的思维灵活做好该事情

Posted yangykaifa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自己定义验证器——用Struts2框架以框架师的思维灵活做好该事情相关的知识,希望对你有一定的参考价值。

面对的问题:自己定义一个18位身份验证器。编写验证器。在validators.xml文件里进行注冊、在验证配置文件里使用?

 

第一部分:理解Struts2中自带的验证器

第二部分:如何通过server(后台)。再次对前台的数据进行验证

第三部分:用Struts2来自己定义验证器(问题解决方式)

 

第一部分:理解Struts2中自带的验证器

Struts2框架中自带的后台server验证分为两种:声明式验证编程式验证

u  声明式验证(重点)

?  对哪个 Action 或 Model 的那个字段进行验证

?  使用什么验证规则

?  假设验证失败, 转向哪一个页面, 显示是什么错误消息

u  编程式验证

 

声明式验证(重点)具体分析:

1、先明白对哪一个 Action 的哪一个字段进行验证: 比方说“age”字段。

2、编写配置文件:

    >把 struts-2.3.15.3\apps\struts2-blank \WEB-INF\src\java\example 下的 Login-validation.xml 文件拷贝到当前 Action 所在的包下。

    >把该配置文件改为: 把Login 改为当前 Action 的名字,比方本例用的到。例如以下文件.

 

E:\Java开发的工具包\struts2.X 开源工具包\struts-2.3.15.1\apps\struts2-blank\WEB-INF\src\java\example具体信息

<!DOCTYPE validators PUBLIC

        "-//Apache Struts//XWork Validator 1.0.2//EN"

        "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">

 

<validators>

    <field name="username">

        <field-validator type="requiredstring">

            <message key="requiredstring"/>

        </field-validator>

    </field>

    <field name="password">

        <field-validator type="requiredstring">

            <message key="requiredstring"/>

        </field-validator>

    </field>

</validators>

    >编写验证规则: 參见 struts-2.3.15.3/docs/WW/docs/validation.html文档就可以(帮助文档——非常有用的文档).

技术分享

1.    conversion validator

2.    date validator

3.    double validator

4.    email validator

5.    expression validator

6.    fieldexpression validator

7.    int validator

8.    regex validator

9.    required validator

10.  requiredstring validator

11.  short validator

12.  stringlength validator

13.  url validator

14.  visitor validator

15.  conditionalvisitor validator

单击date validator进入对应的页面——例如以下图所看到的:

技术分享

拷贝对应的文件进行TestValidationAction-validation.xml配置文件里

> 在配置文件里能够定义错误消息:

    <fieldname="age">

        <field-validator type="int">

            <param name="min">20</param>

            <param name="max">50</param>

            <message>Age needs to be between ${min}and ${max}</message>

        </field-validator>

    </field>

    > 该错误消息也能够国际化操作,具体请參看曾经写的blog《用Struts2进行中英文一键切换——包括具体的源码解析及Struts2国际化原理的理解》

在TestValidationAction-validation.xml文件里加入例如以下信息

<field-validator type="int">

           <param name="min">20</param>

           <param name="max">60</param>

           <message key="error.int"></message>

</field-validator>

再在国际化资源文件里(src/i18n.properties)增加一个键值对: error.int=Age needs to be between ${min}and ${max}

技术分享

3、若验证失败, 则转向 input 的那个 result. 所以须要配置 name=input 的 result

在src/struts.xml文件里加入例如以下信息:

<action name="testValidation" class="com.atguigu.struts2.validation.app.TestValidationAction">

           <result>/success.jsp</result>

          

           <!-- 若验证失败转向的 input -->

           <result name="input">/validation.jsp</result>

</action>

com.atguigu.struts2.validation.app.TestValidationAction的内容

技术分享

     

4、怎样显示错误消息呢 ?

u  若使用的是非 simple(主要是指Struts2中JSP页面《展现出》中主题的设置,一般默认的为XHTML主题。该文件在源码中的位置为: \WebContent\WEB-INF\lib\struts2-core-2.3.15.3.jar\template.simple), 则自己主动显示错误消息。

u  若使用的是simple主题, 则须要 s:fielderror 标签或直接使用 EL 表达式(使用 OGNL)

<!-- 要求年龄必须在 20-50 之间 -->

    <s:form action="testValidation" theme="simple">

       Age: <s:textfield name="age" label="Age"></s:textfield>

       <%--

       ${fieldErrors.age[0] }

       --%>

       <s:fielderror fieldName="age"></s:fielderror>

       <s:submit></s:submit>

    </s:form>

技术分享

技术分享

5、关键点理解:若一个 Action 类能够应答多个 action 请求, 多个 action 请求使用不同的验证规则, 怎么办 ?

 

u  为每个不同的 action 请求定义其相应的验证文件: ActionClassName-AliasName-validation.xml

 

u  不带别名的配置文件: ActionClassName-validation.xml 中的验证规则依旧会发生作用. 能够把各个 action 公有的验证规则配置在当中. 但须要注意的是, 仅仅适用于某一个 action 的请求的验证规则就不要这里再配置了.

技术分享

6、短路验证: 若对一个字段使用多个验证器, 默认情况下会运行全部的验证. 若希望前面的验证器验证没有通过, 后面的就不再验证, 能够使用短路验证

<!-- 针对 age 属性进行验证. 基于字段的验证 -->

    <field name="age">

       <!-- 设置短路验证: 若当前验证没有通过, 则不再进行以下的验证 -->

       <field-validator type="conversion" short-circuit="true">

           <message>^Conversion Error Occurred</message>

       </field-validator>

 

       <field-validator type="int">

           <param name="min">20</param>

           <param name="max">60</param>

           <message key="error.int"></message>

       </field-validator>

    </field>

      

7、 若类型转换失败, 默认情况下还会运行后面的拦截器, 还会进行验证. 能够通过改动 ConversionErrorInterceptor源码的方式使当类型转换失败时, 不再运行兴许的验证拦截器, 而直接返回input的result。

详细过程例如以下:

1、 通过Struts-default.xml文件里找到conversionError拦截器,查看对应的信息。例如以下所看到的:<interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>

2、 通过Ctrl + Shift + T,输入StrutsConversionErrorInterceptor追踪到该方法。之后追踪到该方法的父类ConversionErrorInterceptor

3、 在自己创建的项目src先创建com.opensymphony.xwork2.interceptor包,之后创建ConversionErrorInterceptor.java的Java类。

4、 将追踪到的com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.java源码复制到刚好创建的文件里。

之后再加入例如以下语句。

技术分享

       

8、关于非字段验证: 不是针对于某一个字段的验证.

(src\com.atguigu.struts2.validation.app)

    <!-- 測试非字段验证 -->

     <validator type="expression">

      <param name="expression"><![CDATA[password==password2]]></param>

        <message>Password is not equals to password2</message>

     </validator>

(WebContent\validation.jsp)

Password: <s:password name="password"></s:password>

Password2: <s:password name="password2"></s:password>

( src\com\atguigu\struts2\validation\app\TestValidationAction.java)

在该方法中加入password和password2两个属性,及对应的get和set方法。

public class TestValidationAction extends ActionSupport{

private String password;

   private String password2;

public String getPassword() {

      return password;

   }

   public void setPassword(String password) {

      this.password = password;

   }

   public String getPassword2() {

      return password2;

   }

   public void setPassword2(String password2) {

      this.password2 = password2;

   }

}

细节注意:显示非字段验证的错误消息, 使用 s:actionerror 标签:  (单独一行即可了)<s:actionerror/>

9、不同的字段使用相同的验证规则, 并且使用相同的响应消息 ?

技术分享技术分享技术分享技术分享

第二部分:如何通过server(后台)。再次对前台的数据进行验证

1、声明式验证框架的原理:

u  Struts2 默认的拦截器栈中提供了一个 validation 拦截器

u  每一个详细的验证规则都会相应详细的一个验证器. 有一个配置文件把验证规则名称和验证器关联起来了. 而实际上验证的是那个验证器.

u  该文件位于 com.opensymphony.xwork2.validator.validators下的default.xml

技术分享

技术分享

<interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>

            <interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>

            <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>

            <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>

            <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>

            <interceptor name="filterParams" class="com.opensymphony.xwork2.interceptor.ParameterFilterInterceptor"/>

            <interceptor name="removeParams" class="com.opensymphony.xwork2.interceptor.ParameterRemoverInterceptor"/>

            <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>

            <interceptor name="scopedModelDriven"

                         class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>

            <interceptor name="validation" class="com.opensymphony.xwork2.validator.ValidationInterceptor"/>

            <interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>

            <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>

            <interceptor name="conversionError" class="com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor"/>

            <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>

            <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>

            <interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>

 

 

第三部分:如何用Struts2来自己定义验证器(具体原理阐述)

I、整个流程步骤简单介绍:

A.   自己定义的验证器都须要实现 Validator.(相当于一个JavaBean)

B.   能够选择继承 ValidatorSupport 类或 FieldValidatorSupport 类

C.   若希望实现一个一般的验证器, 则能够继承 ValidatorSupport

D.   若希望实现一个字段验证器, 则能够继承 FieldValidatorSupport

E.   详细实现能够參考眼下已经有的验证器(Struts2自带的验证器).

F.   若验证程序须要接受一个输入參数, 须要为这个參数添加一个对应的属性

 

II、在配置文件里配置验证器(验证配置文件载入顺序):

 

A.   默认情况下, Struts2 会在 类路径的根文件夹下载入 validators.xml 文件. 在该文件里载入验证器.

该文件的定义方式同默认的验证器的那个配置文件一样,能够參看其进行书写: 默认文件位于 com.opensymphony.xwork2.validator.validators 下的 xwork-default.xml

 

B.   若类路径下没有指定的验证器, 则从com.opensymphony.xwork2.validator.validators 下的 default.xml 中的验证器载入

 

III. 自己定义一个18位身份验证器。编写验证器,在validators.xml文件里进行注冊、在验证配置文件里使用?

技术分享

步骤一:书写18位身份证的JavaBean类代码:

/**

 * 身份证第十八位(效验码)的计算方法

 * 将前面的身份证号码17位数分别乘以不同的系数,从第一位到第十七位的系数分别为:

 *       7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2

 * 计算规则:身份证前十七位与这些系数相乘之和相加,用加出来的和除以11。看余数是多少?余数可能是

 *       0, 1,  2 , 3, 4, 5, 6, 7, 8, 9, 10,这十一位数字,其分别相应的最后一位身份证号码为:

 *       1, 0, ‘X‘, 9, 8, 7, 6, 5, 4, 3, 2

 *

 */

public class IDCard {

    final int[] wi = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1 };

    final int[] vi = { 1, 0, ‘X‘, 9, 8, 7, 6, 5, 4, 3, 2 };

    private int[] ai = new int[18];

 

    public IDCard() {}

 

    public boolean Verify(String idcard) {

        if (idcard.length() == 15) {

            idcard = uptoeighteen(idcard);

        }

        if (idcard.length() != 18) {

            return false;

        }

        String verify = idcard.substring(17, 18);

        if (verify.equals(getVerify(idcard))) {

            return true;

        }

        return false;

    }

 

    /**

     * 该方法是新18位身份证。效验码的计算

     *

     * 身份证第十八位(效验码)的计算方法

     * 将前面的身份证号码17位数分别乘以不同的系数,从第一位到第十七位的系数分别为:

     *       7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2

     * 计算规则:身份证前十七位与这些系数相乘之和相加。用加出来的和除以11,看余数是多少?余数可能是

     *       0, 1,  2 , 3, 4, 5, 6, 7, 8, 9, 10,这十一位数字,其分别相应的最后一位身份证号码为:

     *       1, 0, ‘X‘, 9, 8, 7, 6, 5, 4, 3, 2

     */

    public String getVerify(String eightcardid) {

        int remaining = 0;

 

        if (eightcardid.length() == 18) {

            eightcardid = eightcardid.substring(0, 17);

        }

 

        if (eightcardid.length() == 17) {

            int sum = 0;

            for (int i = 0; i < 17; i++) {

                String k = eightcardid.substring(i, i + 1);

                ai[i] = Integer.parseInt(k);

            }

 

            for (int i = 0; i < 17; i++) {

                sum = sum + wi[i] * ai[i];

            }

            remaining = sum % 11;

        }

 

        return remaining == 2 ? "X" : String.valueOf(vi[remaining]);

    }

 

    /**

     * 假设是曾经的身份证号码。则将15位的身份证号码。转换为18位的新的身份证号码

     * 旧身份证号码规则:(15位)

     * 1-6位:地区编码

     * 78位:出生年的后两位(特点:仅仅能对190011日到19991231日出生的人编码——千年虫问题)

     * 9101112位:出生月和日,不足两位的高位补零

     * 131415位:顺序号。无法确认,15位是性别识别码,男性为奇数,女性为偶数。

     *

     */

    public String uptoeighteen(String fifteencardid) {

        String eightcardid = fifteencardid.substring(0, 6);

        eightcardid = eightcardid + "19";

        eightcardid = eightcardid + fifteencardid.substring(6, 15);

        eightcardid = eightcardid + getVerify(eightcardid);

        return eightcardid;

       

    }

   

    public static void main(String[] args) {

       

        String idcard1 = "350211197607142059";

        String idcard2 = "350211197607442059";

       

        IDCard idcard = new IDCard();

        System.out.println(idcard.Verify(idcard1));

        System.out.println(idcard.Verify(idcard2));

    }

}

 

步骤二:一个18位身份验证器的Java类

package com.atguigu.struts2.validation.app;

 

import com.opensymphony.xwork2.validator.ValidationException;

import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;

 

public class IDCardValidator extends FieldValidatorSupport {

 

    @Override

    public void validate(Object object) throws ValidationException {

        //1. 获取字段的名字和值

        String fieldName = getFieldName();

        Object value = this.getFieldValue(fieldName, object);

       

        //2. 验证

        IDCard idCard = new IDCard();

        boolean result = idCard.Verify((String)value);

       

        //3. 若验证失败, ...

        if(!result){

            addFieldError(fieldName, object);

        }

       

    }

}

 

步骤三:书写validators.xml配置文件(能够參看com.opensymphony.xwork2.validator.validators 下的 default.xml 中的配置文件。进行改动)

<?

xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE validators PUBLIC

        "-//Apache Struts//XWork Validator Definition 1.0//EN"

        "http://struts.apache.org/dtds/xwork-validator-definition-1.0.dtd">

 

<!-- START SNIPPET: validators-default -->

<validators>

    <validator name="idcard" class="com.atguigu.struts2.validation.app.IDCardValidator"/>

</validators>

步骤四:页面展现层的代码:

<s:actionerror/>

idCard: <s:textfield name="idCard"></s:textfield>

       <s:fielderror fieldName="idCard"></s:fielderror>

        <s:submit></s:submit>

这样就实现了server后台验证身份证的程序验证器已经部署完毕。










以上是关于自己定义验证器——用Struts2框架以框架师的思维灵活做好该事情的主要内容,如果未能解决你的问题,请参考以下文章

Struts2框架

struts2入门——登陆验证熟悉struts2部署

struts2 登陆时怎样在本页面提示密码输入错误啊??(用验证框架),望给出例子!!

gin框架自定义验证错误提示信息

解决ssh中使用struts2验证框架提示错误后正确无法提交的问题

Struts2-使用验证框架实现数据验证