在Spring MVC中,我有一个@UniqueEmail
自定义休眠验证器(用于在注册时检查电子邮件的唯一性),如下所示:
public class UniqueEmailValidator
implements ConstraintValidator<UniqueEmail, String> {
private UserRepository userRepository;
public UniqueEmailValidator(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public boolean isValid(String email, ConstraintValidatorContext context) {
return !userRepository.findByEmail(email).isPresent();
}
}
现在,我要使用反应性MongoDB迁移到WebFlux,代码如下:
public class UniqueEmailValidator
implements ConstraintValidator<UniqueEmail, String> {
private MongoUserRepository userRepository;
public UniqueEmailValidator(MongoUserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public boolean isValid(String email, ConstraintValidatorContext context) {
return userRepository.findByEmail(email).block() == null;
}
}
首先,如上所述使用block
看起来并不好。其次,它不起作用,这是错误:
Caused by: java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-3
该如何处理?我当然可以使用MongoTemplate阻止方法,但是有没有办法应对这种情况?我可以在服务方法中手动进行操作,但希望将此错误与其他错误(例如“短”密码)一起显示给用户。
答案 0 :(得分:0)
As of Reactor 3.2.0, using blocking APIs inside a parallel or single Scheduler
is forbidden并引发您所看到的异常。因此,当您说它看起来不好时,您就说对了–不仅对您的应用程序真的很不好(它可能阻止对新请求的处理,并使整个过程崩溃),而且如此糟糕,以至于Reactor团队决定认为这是一个错误。
现在的问题是,您想在isValid
调用中完成一些与I / O相关的工作。该方法的完整签名是:
boolean isValid(T value, ConstraintValidatorContext context)
签名表明它正在阻塞(它不返回响应类型,也不提供结果作为回调)。因此,您不允许在其中进行与I / O相关的工作或涉及延迟的工作。在这里,您要对照数据库检查条目,该条目恰好属于该类别。
我不认为您可以在此验证合同中做到这一点,而且我不知道有任何其他选择。
答案 1 :(得分:0)
我遇到了同样的问题,最后我决定使用 ConstraintValidator 检查简单的验证,并检查响应式应用程序逻辑中的响应式验证。我不知道是否有其他更好的解决方案,但它可能是一个不错的方法。