对反应器类型的多项操作或非变革性使用

Multiple actions on, or non-transformative use of, reactor types

我正在努力了解 Spring Boot 和 Reactors(已经离开 Java 将近二十年了)。我正在学习的资源提供了过于基本的示例,并且没有搜索返回任何有意义的信息:只有令人费解的文档无法回答任何问题。

我想要实现的是 - 至少在原则上 - 非常简单。

我有一个功能可以删除 UPLOAD_ROOT 中存储的图像。上传时,图像有一个 name 并被分配了一个 id。然后将该图像存储为 image.id + "-" + image.name,(允许上传具有相同源文件名的多张图像)。 Image class 提供 idname 值的关联,并将其存储在 MongoDB.

数据库Image通过public interface ImageRepository extends ReactiveCrudRepository <Image, String>访问。

删除是 id。我目前的代码(源自一个被文件名删除的版本,并且没有处理名称冲突):

public Mono<Void> deleteImage(String fileId) {
    return Mono.fromRunnable(() -> {
        imageRepository.findById(fileId)
                .map(image -> {
                    Mono<Void> deleteFile = Mono.fromRunnable(() -> {
                        try {
                            Files.deleteIfExists(Paths.get(UPLOAD_ROOT, image.getId() + "-" + image.getName()));
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    });
                    Mono<Void> deleteRecord = Mono.fromRunnable(() -> {
                        imageRepository.delete(image);
                    });
                    return Mono.when(deleteFile, deleteRecord).then();
                });
    }).then();
}

问题是,包裹在 imageRepository.findById(fileId).map(image -> { ... }); 中的 deleteFile 和 deleteRecord 永远不会发生。也不是 Mono.when().

另一种对我来说更有意义的方法是使用非转换的 .map 的替代函数,对提供的 Mono<Image> 的元素进行操作并返回相同的 Mono<Image> 这样可以用它做更多的事情。但是我找不到任何关于启用此功能的参考。

如何让所有嵌套函数真正发生? (我已经尝试了各种方法,每个方法的末尾都带有 .then().subscribe(),但没有任何结果提供一致且功能齐全的结果。)或者是否有一些秘密功能可以让我执行非-转化链?

Mono.fromRunnable 的使用有问题。 试试这个代码:

public Mono<Void> deleteImage(String fileId) {
  return imageRepository.findById(fileId)
           .flatMap(image -> Mono.when(deleteFile(image), deleteRecord(image)).then());
}

private Mono<Void> deleteRecord(Image image) {
  return imageRepository.delete(image);
}

private Mono<Void> deleteFile(Image image) {
  return Mono.fromRunnable(() -> {
    try {
      Files.deleteIfExists(Paths.get(UPLOAD_ROOT, image.getId() + "-" + image.getName()));
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  })
}