面对的问题:自定义一个18位身份验证器,编写验证器,在validators.xml文件中进行注册、在验证配置文件中使用?
第一部分:理解Struts2中自带的验证器
第二部分:怎样通过服务器(后台),再次对前台的数据进行验证
第三部分:用Struts2来自定义验证器(问题解决方案)
第一部分:理解Struts2中自带的验证器
Struts2框架中自带的后台服务器验证分为两种:声明式验证和编程式验证
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文档即可(帮助文档——很实用的文档).
11. short validator 13. url 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、不同的字段使用同样的验证规则, 而且使用同样的响应消息 ?
第二部分:怎样通过服务器(后台),再次对前台的数据进行验证
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位:地区编码 * 7、8位:出生年的后两位(特点:只能对1900年1月1日到1999年12月31日出生的人编码——千年虫问题) * 9、10、11、12位:出生月和日,不足两位的高位补零 * 13、14、15位:顺序号,无法确认,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> |
这样就实现了服务器后台验证身份证的程序验证器已经部署完成。 |
自定义验证器——用Struts2框架以框架师的思维灵活做好该事情
原文地址:http://blog.csdn.net/zhongwen7710/article/details/38052917