springboot~ConstraintValidatorContext验证两个字段内容相同

场景

我在开发修改密码功能,通过原密码和新密码及确认新密码,希望通过ConstraintValidator这个方式来校验新密码和确认新密码,规则是这两个密码需要是相同的。

参考文档

实现

定义Matches注解

@Constraint(validatedBy = SameContentMatchesValidator.class)
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface SameContentMatches {

	String message() default "内容不一致";

	Class<?>[] groups() default {};

	Class<? extends Payload>[] payload() default {};

	String field(); // 新增属性,指定要比较的字段

}

定义DTO对象

@Data
public class UserModifyPasswordDTO implements UserDTO {

	@NotNull
	private String userName;

	@NotNull
	private String password;

	private String newPassword;

	@SameContentMatches(field = "newPassword")
	private String confirmPassword;

}

定义MatchesValidator对象,实现验证的代码逻辑

public class SameContentMatchesValidator implements ConstraintValidator<SameContentMatches, String> {

    private String field;

    @Override
    public void initialize(SameContentMatches constraintAnnotation) {
        this.field = constraintAnnotation.field();
    }

    @Override
    public boolean isValid(String object, final ConstraintValidatorContext context) {
        return true;
    }
}

遇到的问题

  • 在MatchesValidator类中,无法获取到当前对象,除非把SameContentMatches注解作用到当前类上面,而非字段上面。
  • 这个问题应该主是无法解决的,因为你拦截的是字段,在这个ConstraintValidatorContext处理的都是和当前字段有关的信息

应用到类上,代码调整,问题解决

@Constraint(validatedBy = SameContentMatchesValidator.class)
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface SameContentMatches {

	String message() default "内容不一致";

	Class<?>[] groups() default {};

	Class<? extends Payload>[] payload() default {};

	/**
	 * 源字段名
	 * @return
	 */
	String sourceField();

	/**
	 * 目标字段名
	 * @return
	 */
	String destinationField();

}

public class SameContentMatchesValidator implements ConstraintValidator<SameContentMatches, Object> {

	private String sourceField;

	private String destinationField;

	@Override
	public void initialize(SameContentMatches constraintAnnotation) {
		this.sourceField = constraintAnnotation.sourceField();
		this.destinationField = constraintAnnotation.destinationField();
	}

	@Override
	public boolean isValid(Object o, final ConstraintValidatorContext context) {
		final Object sourceFieldVal = BeanUtil.getProperty(o, this.sourceField);
		final Object destinationFieldVal = BeanUtil.getProperty(o, this.destinationField);
		return sourceFieldVal.equals(destinationFieldVal);
	}

}

@Data
@SameContentMatches(sourceField = "confirmPassword", destinationField = "newPassword")
public class UserModifyPasswordDTO implements UserDTO {

	@NotNull
	private String userName;

	@NotNull
	private String password;

	private String newPassword;

	private String confirmPassword;

}

上面的代码SameContentMatches注解出现了弱编码,这块需要再进行优化。