前言
其实早在四月底就在
JR上发表了这篇文章,这次再次搬出来一是为了资料集中,二是做一些修改和更详细的描述.和以往一样入门和介绍就不说了,如何学习在上篇文章Struts2+JFreeChart上有介绍.
正题
1.工程目录结构图:
2.以下依次帖代码:
a). web.xml
<?
xml version="1.0" encoding="UTF-8"
?>
<
web-app
version
="2.4"
xmlns
="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
>
<
filter
>
<
filter-name
>
struts2
</
filter-name
>
<
filter-class
>
org.apache.struts2.dispatcher.FilterDispatcher
</
filter-class
>
</
filter
>
<
filter-mapping
>
<
filter-name
>
struts2
</
filter-name
>
<
url-pattern
>
/*
</
url-pattern
>
</
filter-mapping
>
<
welcome-file-list
>
<
welcome-file
>
ValidatorDate.jsp
</
welcome-file
>
</
welcome-file-list
>
</
web-app
>
b).
struts.xml
<?
xml version="1.0" encoding="UTF-8"
?>
<!
DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"
>
<
struts
>
<
include
file
="struts-validation.xml"
/>
</
struts
>
c).
struts.properties
struts.ui.theme=simple
d).
struts-validation.xml
<!
DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"
>
<
struts
>
<
package
name
="validationExamples"
extends
="struts-default"
namespace
="/validation"
>
<
action
name
="ValidatorField"
class
="com.tangjun.validator.ValidatorAction"
>
<!--
这里input表示验证失败后指定跳转到什么地方去
-->
<
result
name
="input"
type
="dispatcher"
>
/ValidatorDate.jsp
</
result
>
<
result
>
/success.jsp
</
result
>
</
action
>
</
package
>
</
struts
>
e).
ValidatorAction-validation.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
>
<
field
name
="regexYearField"
>
<
field-validator
type
="mydate"
>
<
param
name
="maxYear"
>
2008
</
param
>
<
param
name
="minYear"
>
1900
</
param
>
<
message
>
<![CDATA[
不是一个有效的年份!
]]>
</
message
>
</
field-validator
>
</
field
>
<
field
name
="regexMonthField"
>
<
field-validator
type
="mydate"
>
<
message
>
<![CDATA[
不是一个有效的月份!
]]>
</
message
>
</
field-validator
>
</
field
>
<
field
name
="regexDayField"
>
<
field-validator
type
="mydate"
>
<!--
是否使用正则表达式验证日期
-->
<
param
name
="isRegex"
>
false
</
param
>
<!--
使用自定义正则表达式验证日期
-->
<!--
<param name="expression"></param>
-->
<
message
>
<![CDATA[
当前月份的天数不对!
]]>
</
message
>
</
field-validator
>
</
field
>
</
validators
>
说明:验证文件需要和Action在同一目录下, 验证文件命名规则:验证文件xxxx-validation.xml,这个xxxx就是你前面action的类名字,xxx-xxx-validation.xml第二个xxx表示是别名.
f). validators.xml
<
validators
>
<
validator
name
="required"
class
="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"
/>
<
validator
name
="requiredstring"
class
="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"
/>
<
validator
name
="int"
class
="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"
/>
<
validator
name
="double"
class
="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"
/>
<
validator
name
="date"
class
="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"
/>
<
validator
name
="expression"
class
="com.opensymphony.xwork2.validator.validators.ExpressionValidator"
/>
<
validator
name
="fieldexpression"
class
="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"
/>
<
validator
name
="email"
class
="com.opensymphony.xwork2.validator.validators.EmailValidator"
/>
<
validator
name
="url"
class
="com.opensymphony.xwork2.validator.validators.URLValidator"
/>
<
validator
name
="visitor"
class
="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"
/>
<
validator
name
="conversion"
class
="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"
/>
<
validator
name
="stringlength"
class
="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"
/>
<
validator
name
="regex"
class
="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"
/>
<
validator
name
="mydate"
class
="com.tangjun.validator.DateEx"
/>
</
validators
>
说明:在源码com.opensymphony.xwork2.validator.ValidatorFactory中,在325行至330那一段代码可以看出,如果不能在根目录下找到validators.xml文件,验证框架将调用默认的验证设置,即com.opensymphony.xwork2.
validator.validators目录下default.xml里面的配置信息.最后一个<validator name="mydate" class="com.tangjun.validator.DateEx"/>就是我添加的默认验证器类型.
g). ValidatorAction
package
com.tangjun.validator;
import
com.opensymphony.xwork2.ActionSupport;
/**
* 验证日期
*
*
@author
lzl
*
*/
public
class
ValidatorAction
extends
ActionSupport {
private
static
final
long
serialVersionUID
=
-
4829381083003175423L
;
private
Integer regexYearField;
private
Integer regexMonthField;
private
Integer regexDayField;
public
ValidatorAction()
{
regexYearField
=
null
;
regexMonthField
=
null
;
regexDayField
=
null
;
}
@Override
public
String execute()
throws
Exception {
return
SUCCESS;
}
public
Integer getRegexDayField() {
return
regexDayField;
}
public
void
setRegexDayField(Integer regexDayField) {
this
.regexDayField
=
regexDayField;
}
public
Integer getRegexMonthField() {
return
regexMonthField;
}
public
void
setRegexMonthField(Integer regexMonthField) {
this
.regexMonthField
=
regexMonthField;
}
public
Integer getRegexYearField() {
return
regexYearField;
}
public
void
setRegexYearField(Integer regexYearField) {
this
.regexYearField
=
regexYearField;
}
}
h). BeanUtils
package
com.tangjun.validator;
import
java.text.ParseException;
import
java.text.SimpleDateFormat;
import
java.util.regex.Matcher;
import
java.util.regex.Pattern;
public
class
BeanUtils {
/*
默认验证日期正则表达式
*/
private
static
final
String DateExpression
=
"
(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)
"
;
/**
* 验证日期合法性(通过抛出错误方式来验证)
*
@param
date
*
@return
*/
public
static
boolean
validatorDate(String date) {
//
注意这个地方"yyyy-MM-dd"如果设置成了yyyy-mm-dd的话验证将失灵
SimpleDateFormat sdf
=
new
SimpleDateFormat(
"
yyyy-MM-dd
"
);
//
这个的功能是不让系统自动转换 不把1996-13-3 转换为1997-3-1
sdf.setLenient(
false
);
try
{
sdf.parse(date);
return
true
;
}
catch
(ParseException e) {
return
false
;
}
}
/**
* 使用正则表达式判定日期
*
*
@param
str
*
@param
expression
*
@return
*/
public
static
boolean
regexValidatorDate(String str, String expression) {
//
使用正则表达式进行判定
if
(expression
==
null
||
expression.trim().length()
==
0
)
expression
=
BeanUtils.DateExpression;
Pattern pattern;
//
System.out.println(expression);
pattern
=
Pattern.compile(expression,
2
);
Matcher matcher
=
pattern.matcher(str.trim());
if
(
!
matcher.matches()) {
return
false
;
}
return
true
;
}
}
说明:验证日期的正则表达式就是在网上找的,可以替换成自己的.
i). DateEx
package
com.tangjun.validator;
import
java.util.HashMap;
import
com.opensymphony.xwork2.validator.ValidationException;
import
com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;
public
class
DateEx
extends
FieldValidatorSupport {
private
static
HashMap
<
String, Integer
>
map
=
new
HashMap
<
String, Integer
>
();
/*
默认最大年限
*/
private
static
final
Integer MAX_YEAR
=
2008
;
/*
默认最小年限
*/
private
static
final
Integer MIN_YEAR
=
1900
;
/*
最大年限
*/
private
Integer maxYear;
/*
最小年限
*/
private
Integer minYear;
/*
验证日期的正则表达式
*/
private
String expression;
/*
是否使用正则表达式验证
*/
private
Boolean isRegex;
public
DateEx() {
maxYear
=
null
;
minYear
=
null
;
expression
=
null
;
isRegex
=
false
;
}
public
void
validate(Object object)
throws
ValidationException {
//
获得字段的名字
String fieldName
=
getFieldName();
//
获得输入界面输入的值
String value
=
getFieldValue(fieldName, object).toString();
if
(value
==
null
||
value.length()
<=
0
)
return
;
if
(fieldName.equals(
"
regexYearField
"
))
validateYear(value, object);
else
if
(fieldName.equals(
"
regexMonthField
"
))
validateMonth(value, object);
else
if
(fieldName.equals(
"
regexDayField
"
))
validateDay(value, object);
}
/**
* 验证年份
*
*
@param
object
*
@throws
ValidationException
*/
private
void
validateYear(String value, Object object)
throws
ValidationException {
/*
设置默认值
*/
if
(maxYear
==
null
) {
maxYear
=
MAX_YEAR;
}
if
(minYear
==
null
) {
minYear
=
MIN_YEAR;
}
Integer temp
=
null
;
try
{
temp
=
Integer.valueOf(value);
}
catch
(NumberFormatException ex) {
addFieldErrorEx(getFieldName(), object);
return
;
}
if
(temp
!=
null
) {
if
(temp
>=
minYear
&&
temp
<=
maxYear)
map.put(
"
year
"
, temp);
else
addFieldErrorEx(getFieldName(), object);
}
}
/**
* 验证月份
*
*
@param
object
*
@throws
ValidationException
*/
private
void
validateMonth(String value, Object object)
throws
ValidationException {
try
{
Integer temp
=
Integer.valueOf(value);
if
(temp
!=
null
) {
if
(temp
>=
1
&&
temp
<=
12
)
map.put(
"
month
"
, temp);
else
addFieldErrorEx(getFieldName(), object);
}
}
catch
(NumberFormatException ex) {
addFieldErrorEx(getFieldName(), object);
return
;
}
}
/**
* 验证日期
*
*
@param
object
*
@throws
ValidationException
*/
private
void
validateDay(String value, Object object)
throws
ValidationException {
try
{
Integer temp
=
Integer.valueOf(value);
if
(temp
!=
null
) {
Integer year
=
map.get(
"
year
"
);
Integer month
=
map.get(
"
month
"
);
//
直接使用天数
if
(year
==
null
||
month
==
null
)
{
return
;
}
//
是否使用正则表达式验证
if
(
!
isRegex) {
if
(
!
BeanUtils.validatorDate(year
+
"
-
"
+
month
+
"
-
"
+
temp))
addFieldErrorEx(getFieldName(), object);
}
else
{
String StrDay
=
temp
<
10
?
"
0
"
+
temp.toString() : temp
.toString();
String StrMonth
=
month
<
10
?
"
0
"
+
month.toString()
: month.toString();
//
前面已经验证过了
//
String StrYear = year < 100 ? year < 10 ? "200" + year: "19" + year : "1" + year;
String str
=
year
+
"
-
"
+
StrMonth
+
"
-
"
+
StrDay;
System.out.println(
"
Date:
"
+
str);
if
(expression
==
null
) {
if
(
!
BeanUtils.regexValidatorDate(str,
null
))
addFieldErrorEx(getFieldName(), object);
}
else
{
if
(expression.trim().length()
>
0
) {
if
(BeanUtils.regexValidatorDate(str, expression))
addFieldErrorEx(getFieldName(), object);
}
}
}
map.clear();
}
}
catch
(NumberFormatException ex) {
addFieldErrorEx(getFieldName(), object);
return
;
}
}
/**
* 控制是否只显示一条报错信息
*
*
@param
arg0
*
@param
arg1
*/
private
void
addFieldErrorEx(String arg0, Object arg1) {
//
if (this.getValidatorContext().getFieldErrors().size() == 0)
addFieldError(arg0, arg1);
}
public
Integer getMaxYear() {
return
maxYear;
}
public
void
setMaxYear(Integer maxYear) {
this
.maxYear
=
maxYear;
}
public
Integer getMinYear() {
return
minYear;
}
public
void
setMinYear(Integer minYear) {
this
.minYear
=
minYear;
}
public
String getExpression() {
return
expression;
}
public
void
setExpression(String expression) {
this
.expression
=
expression;
}
public
Boolean getIsRegex() {
return
isRegex;
}
public
void
setIsRegex(Boolean isRegex) {
this
.isRegex
=
isRegex;
}
}
说明:在DateEx里面,这个时候你就可以参照如IntRangeFieldValidator(反编译源码)等他实现的验证器来写自己的验证器了。这里注意了,你在这个类里面每写一个属性(含get set方法),就对应的一个xxxx-validation.xml这个配置文件里面<param name="expression"></param>这个name的名字了,可以在扩展类里面直接获得了,根据传入参数进行自定义方式验证了。如下object是validate传进来的参数,表示你输入的数据对象:
// 获得字段的名字
String fieldName = getFieldName();
// 获得输入界面输入的值
String value = getFieldValue(fieldName, object).toString();
总结
验证器是拦截器即Interceptor实现的,所以并没有看见任何代码把他们和我的action文件关联起来,他们默认的验证了,这方面可以参考Max On Java的文章.