WebFlux 添加阻塞逻辑

WebFlux Adding Blocking Logic

我想知道如何在创建新对象之前进行一些验证检查?

@Override
public Mono<Child> create(CreateChildRequest specs) {

    final String parentId = specs.getParentId();
    // TODO: Check if parent exists
    // parentRepository.getById(parentId) -> returns Mono<Parent>

    final Child newChild = new Child(specs.getParentId(), specs.getName());
    return childRepository.insert(newChild)
            .switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Failed to create child")));
}

如何以非阻塞方式添加验证检查?

也许是这样的东西,没有运行代码,但你明白了它的要点。

@Override
public Mono<Child> create(CreateChildRequest specs) {

    final String parentId = specs.getParentId();
    return parentRepository.getById(parentId)
        .doOnSuccess(parent -> {
            verify(parent).doOnSuccess(() -> {
                childRepository.insert(newChild).doOnError(throwable -> {
                    throw new ResponseStatusException(
                        HttpStatus.BAD_REQUEST,
                        "Failed to create child")
                }).doOnError(throwable -> {
                    // some error handling here if not passing validation.
                })
            })
        })
}

private Mono<Void> verify(Parent parent) {

    if(parent == null)
        return Mono.error(// some error here);
    else
        Mono.empty();
}

如果您只需要做简单的 non-blocking 检查,即检查一些字段(或者通常 - 不需要再玩 Mono/Flux),您可以在doOnNext 运算符并轻松提取到另一个方法。此块内抛出的任何异常都将转换为 Mono.error

final String parentId = specs.getParentId();

    parentRepository.getById(parentId)
        .switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Parent does not exist")))
        .doOnNext(parent -> {
            if (parent.getSomeField() == null) { //this can be easily extracted for readability
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Some field must not be null");
            }
        })
        .then(Mono.just(new Child(specs.getParentId(), specs.getName()))
                .flatMap(childRepository::insert)
                .switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Failed to create child")));

如果执行检查需要涉及另一个 Mono/Flux(例如调用另一个网络服务),则需要使用 'subscribing' 运算符,例如 flatMapzip.

    @Override
    public Mono<Child> create(CreateChildRequest specs) {
        final String parentId = specs.getParentId();

        parentRepository.getById(parentId)
            .switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Parent does not exist")))
            .flatMap(parent -> validate(parent))
            .then(Mono.just(new Child(specs.getParentId(), specs.getName()))
                    .flatMap(childRepository::insert)
                    .switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Failed to create child")));
                }

            }

Mono<Void> validate(Parent parent){
    //some non blocking io logic ending with Mono.empty or Mono.error
}