我正在使用此答案中HibernateValidator指定的相等性验证表单上的两个字段“ password”和“ confirmPassword” 。以下是 约束描述符(验证器接口)。
HibernateValidator
package constraintdescriptor; import constraintvalidator.FieldMatchValidator; import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; @Target({TYPE, ANNOTATION_TYPE}) @Retention(RUNTIME) @Constraint(validatedBy = FieldMatchValidator.class) @Documented public @interface FieldMatch { String message() default "{constraintdescriptor.fieldmatch}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; /** * @return The first field */ String first(); /** * @return The second field */ String second(); /** * Defines several <code>@FieldMatch</code> annotations on the same element * * @see FieldMatch */ @Target({TYPE, ANNOTATION_TYPE}) @Retention(RUNTIME) @Documented public @interface List{ FieldMatch[] value(); } }
以下是 约束验证器 (实现类)。
package constraintvalidator; import constraintdescriptor.FieldMatch; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import org.apache.commons.beanutils.BeanUtils; public final class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object> { private String firstFieldName; private String secondFieldName; public void initialize(final FieldMatch constraintAnnotation) { firstFieldName = constraintAnnotation.first(); secondFieldName = constraintAnnotation.second(); //System.out.println("firstFieldName = "+firstFieldName+" secondFieldName = "+secondFieldName); } public boolean isValid(final Object value, final ConstraintValidatorContext cvc) { try { final Object firstObj = BeanUtils.getProperty(value, firstFieldName ); final Object secondObj = BeanUtils.getProperty(value, secondFieldName ); //System.out.println("firstObj = "+firstObj+" secondObj = "+secondObj); return firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj); } catch (final Exception e) { System.out.println(e.toString()); } return true; } }
以下是与JSP页面映射的验证器bean(commandName="tempBean"由<form:form></form:form>标记指定)。
commandName="tempBean"
<form:form></form:form>
package validatorbeans; import constraintdescriptor.FieldMatch; import javax.validation.constraints.Size; import org.hibernate.validator.constraints.NotEmpty; @FieldMatch.List({ @FieldMatch(first = "password", second = "confirmPassword", message = "The password fields must match", groups={TempBean.ValidationGroup.class}) }) public final class TempBean { @NotEmpty(groups={ValidationGroup.class}, message="Might not be left blank.") private String password; @NotEmpty(groups={ValidationGroup.class}, message="Might not be left blank.") private String confirmPassword; public interface ValidationGroup {}; //Getters and setters }
更新
一切正常,并按预期进行验证。剩下的一件事就是在未显示的TempBean类上方显示指定的错误消息,@FieldMatch即 只有一个问题: 发生验证冲突时如何在JSP页面上显示错误消息?
TempBean
@FieldMatch
(注释@NotEmpty两个字段password,并confirmPassword在TempBean类的作品,并显示指定的消息上违规的事情是不是发生@FieldMatch)。
@NotEmpty
password
confirmPassword
我正在根据此博客中指定的此问题使用 验证组 ,它运行良好,不会导致显示错误消息时出现中断(看起来好像是这样)。
在JSP页面上,这两个字段的指定如下。
<form:form id="mainForm" name="mainForm" method="post" action="Temp.htm" commandName="tempBean"> <form:password path="password"/> <font style="color: red"><form:errors path="password"/></font><br/> <form:password path="confirmPassword"/> <font style="color: red"><form:errors path="confirmPassword"/></font><br/> </form:form>
您可以尝试这样的isValid方法吗?(这肯定对我在现场项目中起作用):
public boolean isValid(final Object value, final ConstraintValidatorContext cvc){ boolean toReturn = false; try{ final Object firstObj = BeanUtils.getProperty(value, firstFieldName ); final Object secondObj = BeanUtils.getProperty(value, secondFieldName ); //System.out.println("firstObj = "+firstObj+" secondObj = "+secondObj); toReturn = firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj); } catch (final Exception e){ System.out.println(e.toString()); } //If the validation failed if(!toReturn) { cvc.disableDefaultConstraintViolation(); //In the initialiaze method you get the errorMessage: constraintAnnotation.message(); cvc.buildConstraintViolationWithTemplate(errorMessage).addNode(firstFieldName).addConstraintViolation(); } return toReturn; }
我还看到您实际上是使用 Object 实现ConstraintValidator接口。它应该是表单中的支持对象:
tempBean //您实际上在commandName中指定的那个。
因此,您的实现应如下所示:
implements ConstraintValidator<FieldMatch, TempBean>
这可能不是这里的问题,但是作为将来的参考,应该是这样。
在FieldMatch接口/注释中,您有两种方法:第一种和第二种,例如,再添加一个称为errorMessage的方法:
Class<? extends Payload>[] payload() default {}; /** * @return The first field */ String first(); /** * @return The second field */ String second(); /** @return the Error Message */ String errorMessage
在Validation类的方法内部查看-您将在那里获得第一个和第二个字段名称。因此,只需添加errorMessage,例如:
private String firstFieldName; private String secondFieldName; //get the error message name private String errorMessagename; public void initialize(final FieldMatch constraintAnnotation) { firstFieldName = constraintAnnotation.first(); secondFieldName = constraintAnnotation.second(); errorMessageNAme = constraintAnnotation.errorMessage(); //System.out.println("firstFieldName = "+firstFieldName+" secondFieldName = "+secondFieldName); }
在isValida内获取它,方法与您对第一个和第二个字段名相同并使用它。