Play 2.6 Java:如何在自定义HTTP动作中获取响应体
在Play 2.6 Java版本中提取Result响应体的正确姿势
嘿,我刚好对Play框架的版本API变化比较熟悉,你遇到的这个问题是因为Play 2.6确实移除了play.core.j.JavaResultExtractor的公开访问权限——框架在这个版本做了API精简,转向更贴合Reactive编程的设计。
你发现的Result.body().consumeData()完全是正确的方向,虽然它带了警示,但只要搞清楚背后的逻辑,就能安全用起来:
先聊聊那个警示的意思
需谨慎使用,若源代表临时流,则实体可能无法再次被消费
说白了就是:响应体的数据流是“一次性”的。如果你的Result响应体来自临时流(比如文件输出流、网络请求返回的流),调用consumeData()把流读完之后,这个流就空了,后续再想从同一个Result里拿响应体就会失败。所以这个方法适合那些只需要一次性获取响应体、之后不再复用该Result的场景——比如单元测试里验证响应内容、记录响应日志这类需求。
具体代码实现
下面给你写个Java的示例,用异步的方式处理(毕竟Play是Reactive框架,推荐异步操作):
import play.mvc.Result; import akka.util.ByteString; import java.util.concurrent.CompletionStage; // 假设你已经拿到了目标Result实例 Result yourResult = ...; // 获取响应体的异步Stage CompletionStage<ByteString> bodyStage = yourResult.body().consumeData(); // 异步处理响应体内容 bodyStage.thenAccept(byteString -> { String bodyContent = byteString.utf8String(); // 这里可以做你需要的操作,比如打印、验证业务逻辑 System.out.println("拿到的响应体:" + bodyContent); }).exceptionally(error -> { // 处理获取过程中出现的异常 error.printStackTrace(); return null; });
如果是在测试场景下,不想写异步逻辑,也可以用Play测试工具类里的封装方法,同步获取响应体:
import play.test.Helpers; // 直接拿到响应体字符串 String bodyContent = Helpers.contentAsString(yourResult);
这个方法内部其实就是帮你处理了consumeData()的异步逻辑,很适合测试用。
要是需要复用Result怎么办?
如果你的场景里,获取完响应体之后还得继续用这个Result,那建议你在拿到ByteString之后,重新构建一个新的Result:
// 先拿到响应体的ByteString ByteString bodyBytes = bodyStage.toCompletableFuture().get(); // 用拿到的字节数据构建新的Result,保留原有的请求头 Result reusableResult = Results.ok(bodyBytes).withHeaders(yourResult.headers());
这样后续使用新的reusableResult就不会有流耗尽的问题了。
内容的提问来源于stack exchange,提问作者Troy Daniels
相关产品推荐
相关产品推荐

