【问题标题】:how to perform validations dynamically in spring?如何在春季动态执行验证?
【发布时间】:2020-08-19 06:48:54
【问题描述】:

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

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

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

所有验证注解都在同一个用户 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

但是我看不懂……

谢谢。

【问题讨论】:

  • 可以添加一些代码示例吗?
  • 非常感谢兄弟...回复@DirkBolte 我已经上传了一些按照您的要求截取的代码
  • 感谢您的代码。我的答案应该仍然与代码示例匹配(虽然它是 Kotlin,但这只是语言)。

标签: spring hibernate customvalidator


【解决方案1】:

由于这是一个自定义验证器,您应该考虑自己添加条件,例如基于仅在保存时生成的 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。听起来您在验证中进行了任何类型的数据库交互。将模型耦合到数据库会破坏封装并限制您的测试能力。添加等式列的唯一性将是另一种选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多