从命令式 try-with-resource 转变为反应式使用,using()

move from imperative try-with-resource to reactive using, using()

我正在尝试从命令式资源尝试转变为反应式资源尝试,但没有成功。我有以下代码要移动。

    private final AmazonS3 amazonS3;
    private final String bucket;
  
    @Override
    public Mono<String> getTemplate(String templateId) {
        return Mono.fromCallable(() -> {
            S3Object s3Object = amazonS3.getObject(bucket, templateId);
            try (s3Object) {
                return IOUtils.toString(s3Object.getObjectContent());
            }
        }).subscribeOn(Schedulers.boundedElastic());
    }

我想使用反应式 try-with-resources 结构重写。 我的第一次尝试是使用 Flux.using

Flux.using(amazonS3.getObject(bucket, templateId),
                s3Object -> Flux.just(IOUtils.toString(s3Object.getObjectContent())),
                S3Object::close);

s3Object 未被转换为 S3Object,因此 getObjectContent 不存在。

然后我查看了 https://projectreactor.io/docs/core/release/reference/ 我想我可能会使用 Disposable,但是我不确定如何用一次性对象包装 S3Object。

有谁知道我怎样才能让它工作? 谢谢

您无法通过您所采用的方法实现这一目标。像您在此处看到的那样 (AWS SDK v1) 采取阻塞 API 并以某种方式包装它以使其具有反应性实际上是不可能的。

但是您可以使用 AWS SDK v2(无论如何您都应该使用它进行新开发),它有一个异步 S3 客户端 (S3AsyncClient),您可以使用它来 return CompleteableFuture<String>:

CompletableFuture<String> contents = s3AsyncClient
    .getObject(GetObjectRequest.builder().build(), new ByteArrayAsyncResponseTransformer<>())
    .thenApplyAsync(rb -> rb.asUtf8String());

然后您可以使用 Mono.fromFuture(contents) 从上面的 CompleteableFuture 获得一个 Mono<String>