自己定义验证器——用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文档就可以(帮助文档——非常有用的文档).
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、不同的字段使用相同的验证规则, 并且使用相同的响应消息 ?
第二部分:如何通过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位:地区编码 * 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> |
这样就实现了server后台验证身份证的程序验证器已经部署完毕。 |