hibernate验证器自定义约束会抛出异常,如何在使用@Valid时在春天捕获它?

时间:2015-07-08 18:23:59

标签: java spring validation exception-handling hibernate-validator

我在Web应用程序中有一个子系统,它在注册过程中执行交互式验证,因此当用户键入用户名,电子邮件,密码等时,会向服务器发出异步请求以执行验证,然后返回一个回复。

对用户名或电子邮件执行的验证之一是,它们尚未用于任何其他用户,这意味着需要对数据库进行查询,这就是我选择在服务器端执行验证的原因。我使用的是Spring Framework 4.1,Spring Data和Hibernate Validator 5.1。

对于可用的用户名和电子邮件验证,按照HV参考指南我创建了自定义约束注释(仅显示用户名1):

@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = UniqueUsernameValidator.class)
@Documented
public @interface UniqueUsername {
    String message() default "{}";
    Class<?>[] groups() default { };
    Class<? extends Payload>[] payload() default { };
}

和验证员类:

public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername,String> {
    private final UserRepository userRepository;
    @Autowired
    public UniqueUsernameValidator(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public void initialize(UniqueUsername annotation) {}

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        // this should be checked with @NotNull at field level
        if (value == null)
            return true;

        User user = userRepository.findByUsername(value);
        if (user == null)
            return true;
        return false;
    }
}

因此,当用户键入表单字段时,有jQuery的AJAX请求,我在其中序列化整个表单并在POST请求中发送,我使用这样的@RestController捕获:

@RequestMapping(value = "/signup/validation/{field}", method = RequestMethod.POST)
public ResponseEntity<ValidationResponse> validateField(
        @PathVariable("field") String field,
        @Valid @ModelAttribute("registrationForm") UserRegistrationForm registrationForm,
        BindingResult result,
        Locale locale) {
    ...
}

问题1 :如果存储库在验证器类中抛出DataAccessException,是否有办法在使用@Valid注释时在其余控制器上捕获它?

问题2 :这种方法有什么问题吗?

注意:我没有在验证器类中捕获DataAccessException,因为我不希望它传播并能够在控制器上捕获它,所以我可以返回一个合适的具有ResponseEntity返回值的HTTP 500代码并通知用户验证存在一些问题,因为如果数据库由于某种原因而关闭,则注册请求将无法持久存在。

注意:我可以在@RestController方法中获取验证器实例,然后在那里执行验证,并且能够轻松捕获异常,这是我使用的解决方法现在,但是为了减少样板和代码重复,我想避免这种情况。

0 个答案:

没有答案