我想组成一个 react 器链,基本上会做如下事情:
- 验证提交的
User
属性,例如firstName
的长度、lastName
或email
的有效性.我会使用下面的验证器。 - 验证提交的
email
没有被其他人使用。为此,我会使用响应式(Reactive)存储库。 - 如果以上所有验证检查均通过,则保存
用户
。
用户:
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@Id
private Integer id;
private String firstName;
private String lastName;
private String email;
}
响应式存储库:
public interface UserRepository extends ReactiveCrudRepository<User, Long> {
@Query("select id, first_name, last_name, email from user u where u.email = :email")
Mono<User> findByEmail(String email);
}
验证器:
@Component
public class UserValidator implements Validator {
private final static String EMAIL = "email";
private static final String FIRST_NAME = "firstName";
private static final String LAST_NAME = "lastName";
@Override
public boolean supports(Class<?> clazz) {
return User.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
User user = (User) target;
rejectIfEmptyOrWhitespace(errors, EMAIL, "email.required");
rejectIfEmptyOrWhitespace(errors, FIRST_NAME, "firstName.required");
rejectIfEmptyOrWhitespace(errors, LAST_NAME, "lastName.required");
validateFirstName(errors, user.getFirstName());
validateLastName(errors, user.getLastName());
validateEmail(errors, user.getEmail());
}
private void validateEmail(Errors errors, String email) {
EmailValidator emailValidator = EmailValidator.getInstance();
if (!emailValidator.isValid(email)) {
errors.rejectValue(EMAIL, "email.invalid");
}
}
private void validateFirstName(Errors errors, String firstName) {
if (firstName.length() < 2) {
errors.rejectValue(FIRST_NAME, "firstName.min");
}
}
private void validateLastName(Errors errors, String lastName) {
if (lastName.length() < 2) {
errors.rejectValue(LAST_NAME, "lastName.min");
}
}
}
处理方法:
public Mono<ServerResponse> saveUser(ServerRequest serverRequest) {
return serverRequest.bodyToMono(User.class)
// Use validator here
.flatMap(this::createUserIfEmailNotExists);
}
辅助方法:
private Mono<ServerResponse> createUserIfEmailNotExists(User user) {
return userRepository.findByEmail(user.getEmail())
.flatMap(existingUser ->
status(BAD_REQUEST).contentType(APPLICATION_JSON)
.body(BodyInserters.fromObject("User already exists."))
)
.switchIfEmpty(
userRepository.save(user)
.flatMap(newUser -> status(CREATED).contentType(APPLICATION_JSON)
.body(BodyInserters.fromObject(newUser)))
);
}
我不确定如何从被动的角度来实现这一点。理想情况下, react 链中将有 3 个步骤映射到上述各点。
这是我尝试过的方法,但我在处理方法参数和返回类型时遇到了问题,这会破坏序列流...
private Mono<ServerResponse> validateUser(User user) {
Errors errors = new BeanPropertyBindingResult(user, User.class.getName());
userValidator.validate(user, errors);
if (errors.hasErrors()) {
return status(BAD_REQUEST).contentType(APPLICATION_JSON)
.body(BodyInserters.fromObject(errors.getAllErrors()));
} else {
return Mono.empty();
}
}
有人可以帮忙吗?
最佳答案
这样怎么样?
private Mono<ServerResponse> validateUser(User user) {
return Mono.just(new BeanPropertyBindingResult(user, User.class.getName()))
.doOnNext(err -> userValidator.validate(user, err))
.filter(AbstractBindingResult::hasErrors)
.flatMap(err ->
status(BAD_REQUEST)
.contentType(APPLICATION_JSON)
.body(BodyInserters.fromObject(err.getAllErrors()))
);
}
private Mono<ServerResponse> createUserIfEmailNotExists(User user) {
return userRepository.findByEmail(user.getEmail())
.flatMap(existingUser ->
status(BAD_REQUEST).contentType(APPLICATION_JSON)
.body(BodyInserters.fromObject("User already exists."))
)
.switchIfEmpty(
validateUser(user)
.switchIfEmpty(
userRepository.save(user)
.flatMap(newUser -> status(CREATED).contentType(APPLICATION_JSON)
.body(BodyInserters.fromObject(newUser)))
)
);
}
关于reactive-programming - 使用项目 react 器将验证包括到 react 链中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57637576/