当前位置: 首页 > 知识库问答 >
问题:

自定义约束验证器不工作(例外)

索和璧
2023-03-14

我对Spring有问题,尤其是ConstraintValidator。我想为包含电子邮件的字段发布自定义验证。它必须是独一无二的。好啊任务很明确,我是这样做的:

UniqueMail。JAVA

@Constraint(validatedBy = UniqueEmailValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface UniqueEmail {
    String message() default "Invalid phone number";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

UniqueMailValidator。JAVA

public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {

    private final UserRepository userRepository;

    public UniqueEmailValidator(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public boolean isValid(String email, ConstraintValidatorContext context) {
        return email != null && !userRepository.findByEmail(email).isPresent();
    }
}

User.java

@Data
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    @NotEmpty(message = "Email should not be empty")
    @Email(message = "Email should be valid")
    @UniqueEmail(message = "Email address is already registered")
    private String email;

    @NotEmpty(message = "Password should not be empty")
    private String password;

    @NotEmpty(message = "Name should not be empty")
    @Size(min = 2, max = 30, message = "Name should be between 2 and 30 characters")
    private String username;

    private boolean enabled = true;

    @Enumerated(value = EnumType.STRING)
    private Role role;
}

用户epository.java

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
}

授权控制器。JAVA

@Controller
@RequestMapping("/auth")
public class AuthController {

    private final UserRepository userRepository;

    private final PasswordEncoder passwordEncoder;

    @Autowired
    public AuthController(UserRepository userRepository, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }

    @GetMapping("/login")
    public String login(Principal principal) {
        if(principal != null)
            return "redirect:/";
        return "auth/login";
    }

    @GetMapping("/register")
    public String register(@ModelAttribute("user") User user, Principal principal) {
        if(principal != null)
            return "redirect:/";
        return "auth/register";
    }

    @PostMapping("/register")
    public String newCustomer(Principal principal, Model model, @ModelAttribute("user") @Valid User user, BindingResult bindingResult) {
        if(principal != null)
            return "redirect:/";

        if(bindingResult.hasErrors())
            return "auth/register";

        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setRole(Role.CUSTOMER);
        userRepository.saveAndFlush(user);

        model.addAttribute("success", true);
        model.addAttribute("user", new User());

        return "auth/register";
    }
}

如果我尝试输入现有的电子邮件一切正常(得到消息电子邮件地址已经注册)。但如果我尝试输入一个新的电子邮件,我得到一个错误Servlet.service()为servlet[调度Servlet]在上下文与路径[]抛出异常[请求处理失败;嵌套异常javax.validation.ValidationExctive: HV000064:无法实例化ConstraintValidator:bla.bla.bla.validator.UniqueEmailValidator.]与根原因。

我正在尝试使用@Component和@Autowung,但得到了相同的结果。我正在尝试使用noArgs构造函数,并获得了NullPointerExctive(UserRepository未注入)。

为什么?我不明白。

共有2个答案

子车轶
2023-03-14

用这种方法解决了这个问题。我知道这是一个拐杖,但我还没有找到另一个解决方案。

@Component
public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {

    private UserRepository userRepository;

    public UniqueEmailValidator() {
    }

    @Autowired
    public UniqueEmailValidator(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public boolean isValid(String email, ConstraintValidatorContext context) {
        if(userRepository == null)
            return true;
        return email != null && !userRepository.findByEmail(email).isPresent();
    }
}

添加了noArgs构造函数,并在isValid函数中添加了ckeck if null userRepository。

阚通
2023-03-14

上面的错误是因为UniqueMailValidator的构造函数为空。另请参见:javax。验证。ValidationException:HV000064:无法实例化ConstraintValidator

您可以使用@Autowired annotation将userRepository注入约束验证器,如下所述:

  • 这里:将Spring Bean注入基于注释的Bean验证器

请注意,在所有相关的控制器方法中,在用户用户之前加上@有效注释

 类似资料:
  • 我在项目中使用bean验证,我想为现有的约束注释编写一个自定义验证器。 例如,我有一个类,它表示一个名为CustomDateTime的日期/时间。在使用此类作为例如出生日期的类中,我想用过去的日期对字段进行注释: 然后,我通过实现ConstraintValidator创建一个自定义验证器 我知道您通常会创建这样的单独注释: 但对我来说,这似乎是双重代码;-) 如何注册要与一起使用的自定义验证器?

  • 我有一个像下面这样的模型对象,带有自定义约束验证器。自定义验证器检查是否填充了fileName或小时。 有一种方法将此作为输入,它验证所有以下条件 > 条件不为空(通过默认验证器) criteria.id不为空(通过默认验证器) criteria.name不为空(通过默认验证器) 标准文件名或小时不为空(通过自定义验证器) 空评估(@NotNull@有效标准标准){} 现在,当我为这个模型类编写单

  • 我有一个自定义注释@UniqueModel,它由ConstraintValidator验证: 问题是,我需要在调用存储库的safe()-方法之前进行验证,否则字段注入将无法工作。 因此,我创建了一个带有@Valid注释的委托方法,以便在以下情况之前强制进行唯一验证: 不幸的是,这不起作用,似乎@Valid注释被Spring忽略了。 我如何确保验证的正确时间?

  • 我已经为此斗争了好几天,我已经阅读了这里的所有讨论,但没有解决方案...... 我有一个自定义约束… 独一无二.java 这是由UniqueConstraintValidator使用的.java 现在,我的模型有这个注释,我需要在其中验证字段的唯一性 现在,我知道自定义注释在更新现有对象时不起作用,但是现在我需要了解它是如何工作的。假设我们想要添加一个新对象。 当我试图保存一个已经存在的值时,我得

  • 我有以下验证器,用于验证更新请求。 object.getIdCreditor()有一个值,但是findById方法的执行["CreditorRepository.findById(object.getIdCreditor())" ] 进入NullPointer异常 我不明白怎么了。

  • TLDR:我想要在单独的模块中单独的自定义bean验证定义及其ConstraintValidator实现。为此,我必须使用ConstraintMmap手动注册。它适用于带注释的类。但是定义的绑定不共享/可用于通过validation-constraints.xml.定义的验证如何修复?我试图调试它,以找出它在哪里初始化以及为什么会出现问题,但初始化这些远非易事。 动机: 一) 分离模块:如果API