我有一个反应式Web应用程序(Spring WebFlux(,我通过Azure存储中的POST API存储用户配置文件图像。如果存储桶不存在,我需要为用户创建一个存储桶。
服务层方法如下所示: (其中包含嵌套的 flatMaps - 这在反应式应用程序中被认为是一种不好的做法,并且是一种代码异味。我想重构这样没有嵌套的flatMap。有什么办法可以做到这一点吗?
public Mono<BlockBlobItem> processAndUpload(FilePart filePart) {
return Mono.subscriberContext().flatMap(context -> {
String userId = context.get(USER_ID_CONTEXT);
BlobContainerAsyncClient blobContainerClient = blobServiceAsyncClient.getBlobContainerAsyncClient(userId);
return blobContainerClient.exists()
.doOnEach(logOnNext(doesContainerExist -> {
if (doesContainerExist) {
LOGGER.info(STORAGE_CONTAINER_EXISTS_MSG);
} else {
LOGGER.info(STORAGE_CONTAINER_DOES_NOT_EXIST_MSG);
}
}))
.doOnEach(logOnError(err -> LOGGER.error(CONTAINER_CHECK_FAILURE_MSG, err.getMessage(), err)))
.flatMap(doesContainerExist -> {
if (doesContainerExist) {
return uploadFile(filePart, blobContainerClient, userId);
} else {
return blobContainerClient.createWithResponse(null, null)
.doOnEach(logOnComplete(response -> LOGGER.info(CONTAINER_CREATION_SUCCESS_MSG)))
.doOnEach(logOnError(err -> LOGGER.error(CONTAINER_CREATION_FAILURE_MSG, err.getMessage(), err)))
.then(uploadFile(filePart, blobContainerClient, userId));
}
});
});
}
恐怕只要您需要这两种上下文,嵌套flatMap
是唯一的方法。
如果您谈论重构,我会将 lambda 表达式(或至少它们的右侧(移出该方法以实现可读性。还可以考虑先使用map
来获取userId
,只要您不需要初始context
。
public Mono<BlockBlobItem> processAndUpload(FilePart filePart) {
return Mono.subscriberContext()
.map(context -> context.get(USER_ID_CONTEXT))
.flatMap(userId -> {
var client = blobServiceAsyncClient.getBlobContainerAsyncClient(userId);
return client.exists()
.doOnEach(logOnNext(doesContainerExistLambda))
.doOnEach(logOnError(errLambda))
.flatMap(doesExist -> existenceHandler(filePart, client, userId));
}
);
}
名为doesContainerExistLambda
、errLambda
、existenceHandler
的方法和 lambda 表达式是根据您的需要和注意事项进行更改的主题。代码片段的重点是突出显示可以移动到其他地方的内容。