对反应器类型的多项操作或非变革性使用
Multiple actions on, or non-transformative use of, reactor types
我正在努力了解 Spring Boot 和 Reactors(已经离开 Java 将近二十年了)。我正在学习的资源提供了过于基本的示例,并且没有搜索返回任何有意义的信息:只有令人费解的文档无法回答任何问题。
我想要实现的是 - 至少在原则上 - 非常简单。
我有一个功能可以删除 UPLOAD_ROOT
中存储的图像。上传时,图像有一个 name
并被分配了一个 id
。然后将该图像存储为 image.id + "-" + image.name
,(允许上传具有相同源文件名的多张图像)。 Image
class 提供 id
和 name
值的关联,并将其存储在 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);
}
})
}
我正在努力了解 Spring Boot 和 Reactors(已经离开 Java 将近二十年了)。我正在学习的资源提供了过于基本的示例,并且没有搜索返回任何有意义的信息:只有令人费解的文档无法回答任何问题。
我想要实现的是 - 至少在原则上 - 非常简单。
我有一个功能可以删除 UPLOAD_ROOT
中存储的图像。上传时,图像有一个 name
并被分配了一个 id
。然后将该图像存储为 image.id + "-" + image.name
,(允许上传具有相同源文件名的多张图像)。 Image
class 提供 id
和 name
值的关联,并将其存储在 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);
}
})
}