在Struts中应用Validator进行两个字段的比较的方法。

在struts中进行采用Validator进行输入验证有很多好处,完全可以通过修改XML文件来根据客户的要求定制数据验证而不用修改代码。但是Valiator没有提供现成的进行两个字段比较的验证方法,如验证输入密码和确认密码一致,后面的日期必须大于前面的日期等等。下面是我实现的两个字段进行比较的验证方法,可以进行两个字段是字符串、日期、数字类型的数据的比较。下面是我的实现方法,望指正:

package com.sysway.quintum.validator;

import java.io.Serializable;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.DecimalFormat;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.validator.Field;
import org.apache.commons.validator.GenericTypeValidator;
import org.apache.commons.validator.GenericValidator;
import org.apache.commons.validator.ValidatorAction;
import org.apache.commons.validator.ValidatorUtil;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.validator.Resources;
import com.sysway.quintum.validator.WrapData;

/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: Sysway Co.Ltd</p>
* @author chen jianxiong
* @version 1.0
* @usage:
*<validator name="compareTwoFields"
classname="com.sysway.quintum.validator.CompareTwoFieldsValidator"
method="validateTwoFields"
msg="errors.twofields"/>
<field property="password"
depends="required,twofields">
<arg0 key="typeForm.password.displayname"/>
<var>
<var-name>secondField</var-name>
<var-value>confirmedPassword</var-value>
</var>
<var>
<var-name>dataType</var-name>
<var-value>String</var-value>
</var>
<var>
<var-name>logicOperate</var-name>
<var-value>Great</var-value>
</var>
<var>
<var-name>pattern</var-name>
<var-value>yyyy-mm-dd</var-value>
</var>
</field>
* @logicOperate:equal, greaterEqual, greaterThan, lessEqual, lessThan, notEqual
* @dataType:String,date,Number
* @pattern:yyyy-mm-dd

*/


public class CompareTwoFieldsValidator implements Serializable {
public static boolean validateTwoFields(Object bean, ValidatorAction va,
Field field, ActionErrors errors, HttpServletRequest request) {
String firstFieldValue = ValidatorUtil.getValueAsString(bean, field.getProperty());
String secondFieldName = field.getVarValue(
"secondField");
String secondFieldValue = ValidatorUtil.getValueAsString(bean, secondFieldName);
if (!GenericValidator.isBlankOrNull(firstFieldValue) &&
!GenericValidator.isBlankOrNull(secondFieldValue)) {
String logicOperate = field.getVarValue(
"logicOperate");
String dataType = field.getVarValue(
"dataType");
String pattern = field.getVarValue(
"pattern");
// System.out.println("firstFieldValue:" + firstFieldValue + "," +
// "secondFieldName:" + secondFieldName + "," +
// "secondFieldValue:" + secondFieldValue + "," +
// "logicOperate:" + logicOperate + "," +
// "dataType:" + dataType + "," +
// "pattern:" + pattern);
Object oValue1 = null, oValue2 = null;
try {
if (dataType.equals(
"Number")) {
DecimalFormat df = new DecimalFormat();
oValue1 = df.parse(firstFieldValue);
oValue2 = df.parse(secondFieldValue);
}
else if (dataType.equals(
"Date")) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
oValue1 = sdf.parse(firstFieldValue);
oValue2 = sdf.parse(secondFieldValue);
}
else {
oValue1 = (String ) firstFieldValue;
oValue2 = (String ) secondFieldValue;
}
}
catch (Exception ex) {
ex.printStackTrace();
return false;
}
try {
if (logicOperate.equals(
"equal")) {
if (WrapData.compareTo(oValue1, oValue2) == WrapData.EQUAL)
return true;
else {
errors.add(field.getKey(),
Resources.getActionError(request, va, field));
return false;
}
}
else if (logicOperate.equals(
"greaterThan")) {
if (WrapData.compareTo(oValue1, oValue2) == WrapData.GREATERTHAN)
return true;
else {
errors.add(field.getKey(),
Resources.getActionError(request, va, field));
return false;
}
}
else {
errors.add(field.getKey(),
Resources.getActionError(request, va, field));
return false;
}
/* else if (logicOperate.equals("greaterEqual")) {
}
else if (logicOperate.equals("lessEqual")) {
}
else if (logicOperate.equals("lessThan")) {
}
else if (logicOperate.equals("notEqual")) {
}*/

} catch (Exception e) {
errors.add(field.getKey(),
Resources.getActionError(request, va, field));
return false;
}
}
else {
errors.add(field.getKey(),
Resources.getActionError(request, va, field));
return false;
}
}
}

validation.xml使用示例:

<form name="changePasswordForm">
<field property=
"oldPassword" depends="required">
<arg0 key=
"oldPassword"/>
</field>

<field property=
"password" depends="required">
<arg0 key=
"password"/>
</field>

<field property=
"confirmedPassword" depends="twoFields">
<arg0 key=
"confirmedPassword"/>
<arg1 key=
"${var:logicOperate}"/>
<arg2 key=
"${var:secondField}"/>
<var>
<var-name>secondField</var-name>
<var-value>password</var-value>
</var>
<var>
<var-name>dataType</var-name>
<var-value>String</var-value>
</var>
<var>
<var-name>logicOperate</var-name>
<var-value>equal</var-value>
</var>
</field>
</form>

validation-rules.xml中定义规则:

<validator name="twoFields"
classname=
"com.sysway.quintum.validator.CompareTwoFieldsValidator"
method=
"validateTwoFields"
methodParams=
"java.lang.Object,
org.apache.commons.validator.ValidatorAction,
org.apache.commons.validator.Field,
org.apache.struts.action.ActionErrors,
javax.servlet.http.HttpServletRequest
"
msg=
"errors.twoFields">
</validator>

application_zh.properties中定义的错误消息:
errors.twoFields={0}必须{1}{2}

怎么JDon现在发帖子时总会贴不上。害得我辛辛苦苦写的一段没有了:(:( faint.不写了。

This is another way.........

http://www.raibledesigns.com/page/rd/20030226struts_validator_validating_two_fields

How To Add a TwoFields Validator

Step 1: Create a class with a validateTwoFields method. In my code, my class is ValidationUtil and has the following method:

public static boolean validateTwoFields(Object bean, ValidatorAction va,
Field field, ActionErrors errors,
HttpServletRequest request) {
String value =
ValidatorUtil.getValueAsString(bean, field.getProperty());
String sProperty2 = field.getVarValue("secondProperty");
String value2 = ValidatorUtil.getValueAsString(bean, sProperty2);

if (!GenericValidator.isBlankOrNull(value)) {
try {
if (!value.equals(value2)) {
errors.add(field.getKey(),
Resources.getActionError(request, va, field));

return false;
}
} catch (Exception e) {
errors.add(field.getKey(),
Resources.getActionError(request, va, field));

return false;
}
}

return true;
}
Step 2: Edit validator-rules.xml to contain the "twofields" rule.

<validator name="twofields"
classname="org.appfuse.webapp.util.ValidationUtil" method="validateTwoFields"
methodParams="java.lang.Object,
org.apache.commons.validator.ValidatorAction,
org.apache.commons.validator.Field,
org.apache.struts.action.ActionErrors,
javax.servlet.http.HttpServletRequest"
depends="required" msg="errors.twofields">
<javascript><![CDATA[
function validateTwoFields(form) {
var bValid = true;
var focusField = null;
var i = 0;
var fields = new Array();
oTwoFields = new twofields();
for (x in oTwoFields) {
var field = form[oTwoFields[x][0]];
var secondField = form[oTwoFields[x][2]("secondProperty")];

if (field.type == 'text' ||
field.type == 'textarea' ||
field.type == 'select-one' ||
field.type == 'radio' ||
field.type == 'password') {

var value;
var secondValue;
// get field's value
if (field.type == "select-one") {
var si = field.selectedIndex;
value = field.options[si].value;
secondValue = secondField.options[si].value;
} else {
value = field.value;
secondValue = secondField.value;
}

if (value != secondValue) {

if (i == 0) {
focusField = field;
}
fields[i++] = oTwoFields[x][1];
bValid = false;
}
}
}

if (fields.length > 0) {
focusField.focus();
alert(fields.join('\n'));
}

return bValid;
}]]></javascript>
</validator>
Step 3: Configure validation for your form in validation.xml:

<field property="password"
depends="required,twofields">
<msg
name="required"
key="errors.required"/>
<msg
name="twofields"
key="errors.twofields"/>

<arg0 key="userForm.password"/>
<arg1
key="userForm.confirmPassword"
/>
<var>
<var-name>secondProperty</var-name>
<var-value>confirmPassword</var-value>
</var>
</field>
Where errors.twofields=The '{0}' field has to have the same value as the '{1}' field. An alternative to Step 3 is to use XDoclet to generate your validation.xml. This requires (1) configuring XDoclet (of course) and (2) adding some @struts tags to your form on the setPassword method.

/**
* Returns the password.
* @return String
*
* @struts.validator type="required" msgkey="errors.required"
* @struts.validator type="twofields" msgkey="errors.twofields"
* @struts.validator-args arg1resource="userForm.password"
* @struts.validator-args arg1resource="userForm.confirmPassword"
* @struts.validator-var name="secondProperty" value="confirmPassword"
*/
public String setPassword() {
return password;
}

楼上是用于比较两个口令是否一致,这只是我的方法中的一种情况。:):)。我的实现也是参考了kuang提到的示例。

好文章,顶一下。

想看一下com.sysway.quintum.validator.WrapData类是怎么写的,^_^,能不能show一下?

因为我们大部分是比较字符型、日期型、和数字型。所以我仅实现了这三种比较。

public static int compareTo(Object data, Object anotherData) {
if (!isSameType(data, anotherData))
return NOTSAMETYPE;
if (anotherData instanceof String) {
String value2 = (String ) anotherData;
if (value2.compareTo(data) < 0)
return LESSTHAN;
else if (value2.compareTo(data) > 0)
return GREATERTHAN;
else
return EQUAL;
}
else if (anotherData instanceof Number) {
Double value2 = (Double ) anotherData;
if (value2.compareTo(data) < 0)
return LESSTHAN;
else if (value2.compareTo(data) > 0)
return GREATERTHAN;
else
return EQUAL;
}
if (anotherData instanceof Date) {
Date value2 = (Date ) anotherData;
if (value2.compareTo(data) < 0)
return LESSTHAN;
else if (value2.compareTo(data) > 0)
return GREATERTHAN;
else
return EQUAL;
}
else
return UNKNOWNERROR;
}

public static boolean isSameType(Object data, Object anotherData) {
return data.getClass() == anotherData.getClass();
}

public static final int EQUAL = 1;
public static final int GREATEREQUAL = 2;
public static final int GREATERTHAN = 3;
public static final int LESSEQUAL = 4;
public static final int LESSTHAN = 5;
public static final int NOTEQUAL = 6;
public static final int NOTSAMETYPE = 7;
public static final int UNKNOWNERROR = 8;
public WrapData(Object data, Class type) {
super();
this.data = data;
this.type = type;
}

public WrapData(Object data) {
this(data, data.getClass());
}