如何在春季动态执行验证?

问题描述

我为唯一的电子邮件做了一个自定义验证注释(当用户注册自己时,程序会检查数据库中是否已存在电子邮件)。

一切正常,但是当我需要修改用户信息而不创建新信息时,我遇到一个问题,提示“电子邮件已经在使用中”

我可以以某种方式仅关闭@EmailAvailablity验证(我需要其他验证方式,例如电子邮件模式和密码验证)吗?

所有验证注释都在同一个User Bean中。

这些是我的自定义验证者课程

  1. 用户可用
package com.vicky.finalYearProject.customValidations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Constraint(validatedBy = UserAvailabilityValidator.class)
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserAvailability {
    
    public String message() default "Email is already Registered";
    
    public Class<?>[] groups() default { };
    
    public Class<? extends Payload>[] payload() default { };
    
}
  1. 约束验证器
package com.vicky.finalYearProject.customValidations;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import com.vicky.finalYearProject.Service.CheckUserAvailabilityService;

public class UserAvailabilityValidator implements ConstraintValidator<UserAvailability,String>{

    CheckUserAvailabilityService availabilityService = new CheckUserAvailabilityService();
    
    @Override
    public void initialize(UserAvailability constraintAnnotation) {
        ConstraintValidator.super.initialize(constraintAnnotation);
        
    }
    
    @Override
    public boolean isValid(String email,ConstraintValidatorContext context) {
        return availabilityService.isAvailable(email);//return true or false;
    }

}

我检查了一个类似的问题:

How to prevent Spring validation on update

但我听不懂...

谢谢。

解决方法

由于这是一个自定义验证程序,因此您应该考虑自己添加条件,例如基于仅在保存时生成的ID。为此,将其设置为类级别的约束将很有帮助,使您可以检查类的多个值。

类似的东西:

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Constraint(validatedBy = [EmailAvailabilityValidator::class])
annotation class EmailAvailability(
    val message: String = "Email must be available",val groups: Array<KClass<*>> = [],val payload: Array<KClass<out Any>> = []
)

class EmailAvailabilityValidator : ConstraintValidator<EmailAvailability,User> {

    override fun isValid(value: User?,context: ConstraintValidatorContext?): Boolean {
        if (value == null) return true
        if (value.id != null) return true // don't execute it on saved entities
        // your extra validation
    }
}

或者,当使用Hibernate时,以下是有关仅在插入代码上运行验证的建议:Hibernate validations on save (insert) only

此外,我将考虑将此检查移出bean。听起来您在验证中进行了任何类型的数据库交互。将模型与数据库耦合会破坏封装并限制您的测试功能。添加e.q.列的唯一性是替代方法。