Helidon SE 2.5.0:转Single<List<ReadableBodyPart>>后无法读取多部件
Helidon SE 2.5.0 收集ReadableBodyPart列表失效的解决方案
问题场景
在Helidon SE 2.5.0版本中,ReadableMultiPart已被标记为废弃,尝试通过asStream(ReadableBodyPart.class)结合collectList()获取请求体的BodyPart列表时,代码无法正常输出日志:
serverRequest.content().asStream(ReadableBodyPart.class) .collectList() .forSingle(readableBodyParts -> readableBodyParts. forEach(bodyPart -> { log.atInfo().log("I'm working..."); bodyPart.drain(); }));
但直接使用forEach()遍历流的代码却能正常工作:
serverRequest.content().asStream(ReadableBodyPart.class) .forEach(readableBodyPart ->{ log.atInfo().log("I'm working..."); readableBodyPart.drain(); });
解决方案
核心问题在于collectList()收集所有BodyPart后,直接调用bodyPart.drain()是异步操作,未等待其完成就结束了回调逻辑,导致日志未触发且资源未正确释放。同时Reactive流中收集后的BodyPart存在生命周期依赖,需确保异步操作执行完成。以下是两种可行修改方案:
方案1:用CompletableFuture等待所有drain任务完成
serverRequest.content().asStream(ReadableBodyPart.class) .collectList() .forSingle(readableBodyParts -> { // 将每个drain操作转为CompletableFuture CompletableFuture<Void>[] drainTasks = readableBodyParts.stream() .map(bodyPart -> { log.atInfo().log("I'm working..."); return bodyPart.drain().toCompletableFuture(); }) .toArray(CompletableFuture[]::new); // 阻塞等待所有drain任务执行完毕 CompletableFuture.allOf(drainTasks).join(); });
方案2:遵循Reactive范式链式处理异步流
serverRequest.content().asStream(ReadableBodyPart.class) .collectList() // 将收集到的列表重新转为流 .flatMapIterable(parts -> parts) // 输出处理日志 .invoke(bodyPart -> log.atInfo().log("I'm working...")) // 异步执行drain并等待操作完成 .flatMap(bodyPart -> bodyPart.drain()) // 订阅流并处理结果与异常 .subscribe().with( unused -> {}, error -> log.atSevere().log("处理BodyPart失败", error) );
方案1适合简单场景,通过阻塞等待确保所有异步任务完成;方案2更贴合Helidon的异步编程模型,遵循Reactive流的处理规范。
内容的提问来源于stack exchange,提问作者Vamsi Krishna DS
相关产品推荐
相关产品推荐

