无法以反应方式 return webflux 中的请求

Unable to return a request within webflux in reactive manner

这是我的代码中的以下流程: 用户调用创建代理端点,包含代理名称和布尔字段 ->

路由器函数接收调用,传递给处理程序 ->

Handler 将请求主体转换为 Mono,将那个 Mono 传递给服务 ->

Service 将代理保存到 DB,在此过程中生成一个 ID,然后创建一个 Response 对象,其中包含用 Mono 包装的 ID,returns Response 返回给 Handler。

这是我卡住的部分。为了保持反应性方法,我必须将 Agency 保存到 Db 并在 Mono 的“doOnNext()”部分中创建 ID。但是,我无法 return 我从 DB 获得的 ID 以创建响应对象。

实现此目的的被动方式是什么?提前致谢!

public RouterFunction<ServerResponse> createAgency() {
        return RouterFunctions
                .route(POST("/agency").and(accept(MediaType.APPLICATION_JSON)), handler::createAgency);
    }
@Component
@AllArgsConstructor
public class AgencyHandler {

    private final AgencyServiceImpl service;

    @NonNull
    public Mono<ServerResponse> createAgency(ServerRequest request){
        Mono<CreateAgencyRequest> agency = request.bodyToMono(CreateAgencyRequest.class);

        Mono<CreateAgencyResponse> response = service.createAgency(agency);

        return ServerResponse.created(URI.create("/agency"))
                .contentType(MediaType.APPLICATION_JSON)
                .body(response, CreateAgencyResponse.class);
    }
}
@Service
@AllArgsConstructor
public class AgencyServiceImpl implements AgencyService {
    private final AgencyRepository agencyRepository;
    private final UuidGenerator uuidGenerator;

    public Mono<CreateAgencyResponse> createAgency(Mono<CreateAgencyRequest> request) {
        UUID id;
        request.doOnNext(agency -> {
            UUID agencyId = uuidGenerator.getUUID();
            Mono<Agency> newAgency = Mono.just(
                new Agency(
                    agencyId,
                    agency.getFields().getName()
            ));

            //repository.save(newAgency)

            //return Mono.just(new CreateAgencyResponse(new CreateAgencyResponseData(agencyId.toString())));
        });

        // return request
        return Mono.just(new CreateAgencyResponse(new CreateAgencyResponseData(agencyId.toString())));
    }
}

doOnNext是为了副作用,你要找的是flatMap

return request.flatMap(agency -> {
    final UUID agencyId = uuidGenerator.getUUID();
    return repository.save(new Agency(agencyId, agency.getFields().getName()))
        .thenReturn(agencyId);
}).flatMap(id -> ServerResponse.ok()
    .bodyValue(new CreateAgencyResponseData(agencyId.toString()))
    .build());

在没有编译器检查代码的情况下编写此代码,但您应该了解它的要点。

doOnNext 不是执行 I/O 绑定操作(例如数据库访问)的好选择。您应该改用 flatmap。另外,请查看 map 用于同步、1 对 1 转换的运算符。

最终代码应如下所示:

  public Mono<CreateAgencyResponse> createAgency(Mono<CreateAgencyRequest> request) {
    return request.map(req -> new Agency(uuidGenerator.getUUID(), req.getFields().getName()))
        .flatMap(agency -> repository.save(agency))
        .map(agency -> new CreateAgencyResponse(new CreateAgencyResponseData(agency.getAgencyId())));
  }

像下面这样的东西应该可以解决问题:

@Service
@AllArgsConstructor
public class AgencyServiceImpl implements AgencyService {
    private final AgencyRepository agencyRepository;
    private final UuidGenerator uuidGenerator;

    public Mono<CreateAgencyResponse> createAgency(Mono<CreateAgencyRequest> request) {
        UUID agencyId = uuidGenerator.getUUID();

        return request.flatMap(createAgencyRequest -> {
            Agency agency = new Agency(agencyId, agency.getFields().getName();
            return repository.save(newAgency);    
        }).map(saved ->
            new CreateAgencyResponse(new CreateAgencyResponseData(agencyId.toString()));
        )
    }
}

您将在 flatMap 操作中创建 Agency 并将其存储在数据库中。我假设你的 repository 也是反应性的,所以它也应该 return Mono,因此 flatMap 操作。之后,您只需要映射任何 repository returned(您可能希望在此处基于对数据库的成功操作有一些逻辑)来创建 CreateAgencyResponse.