自定义constraintvalidator不工作(异常)

beq87vna  于 2021-07-12  发布在  Java
关注(0)|答案(2)|浏览(854)

我对spring有一个问题,特别是constraintvalidator。我想为包含电子邮件的字段发布自定义验证。它必须是独一无二的。好 啊。任务很明确,我是这样做的:
uniqueemail.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 {};
}

uniqueemailvalidator.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();
    }
}

用户.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;
}

用户存储库.java

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

authcontroller.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[dispatcherservlet]引发异常[请求处理失败;嵌套的异常为javax.validation.validationexception:hv000064:无法示例化constraintvalidator:bla.bla.bla.validator.uniqueemailvalidator.]和“根本原因”。
我尝试使用@component和@autowired,但得到了相同的结果。我正在尝试使用noargs构造函数并得到nullpointerexception(没有注入userrepository)。
为什么?我不明白。

v2g6jxz6

v2g6jxz61#

上面的错误是因为uniqueemailvalidator的构造函数为空。另请参见:javax.validation.validationexception:hv000064:无法示例化constraintvalidator
您可以使用@autowired annotation将userrepository注入到约束验证器中,如下所述:
这里:将springbean注入到基于注解的bean验证器中
在这里:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#validation-Bean验证Spring约束
请注意在所有相关的控制器方法中,将@valid注解放在user之前

ua4mk5z4

ua4mk5z42#

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

@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。

相关问题