Scala Play WS获取超长JSON响应不完整问题求助
解决Play框架WS异步调用超长JSON数组响应问题
你遇到的问题根源有两个:
- 使用
get()方法时,受限于Play WS默认的响应大小限制,导致超长JSON被截断; - 用
stream()后调用bodyAsBytes是阻塞操作,违背异步模型,因此Akka抛出警告。
正确处理方案
1. 异步收集完整响应体(推荐)
用Akka Stream的异步Sink收集响应流,既避免阻塞,又能确保获取完整响应内容:
import akka.actor.ActorSystem import akka.stream.Materializer import akka.util.ByteString import play.api.libs.json.{JsArray, Json} import play.api.libs.ws.ahc.StandaloneAhcWSClient import scala.concurrent.{ExecutionContext, Future} import scala.concurrent.duration._ // 复用WS客户端(禁止每次请求新建) implicit val system: ActorSystem = ActorSystem("ws-client") implicit val materializer: Materializer = Materializer(system) implicit val ec: ExecutionContext = system.dispatcher val wsClient = StandaloneAhcWSClient() // 替换为你的实际Provider分组获取逻辑 val processRequests = providers.flatMap { providerGroups => // 异步批量处理请求 Future.traverse(providerGroups) { providers => val npis = providers.map(p => ("npi", p.npi.get)) val request = wsClient.url("你的接口地址") .addHttpHeaders("Accept" -> "application/json") .withQueryStringParameters(npis: _*) .withRequestTimeout(15.minutes) request.stream().flatMap { response => if (response.status == 200) { // 异步拼接所有响应字节,无阻塞 response.bodyAsSource.runFold(ByteString.empty)(_ ++ _).map { fullBody => // 解析为JsonArray Json.parse(fullBody.utf8String).as[JsArray] } } else { Future.failed(new Exception(s"请求失败,状态码:${response.status}")) } } } } // 处理最终结果 processRequests.onComplete { case Success(jsonArrays) => // 在这里处理所有解析后的JsonArray println("所有请求处理完成") wsClient.close() system.terminate() case Failure(e) => println(s"处理出错:${e.getMessage}") wsClient.close() system.terminate() }
2. 调整WS配置(适用于响应非极端大的场景)
如果响应大小可控,可修改application.conf取消响应大小限制,继续使用get()方法:
# -1表示无限制,也可设置具体字节数(如100MB=104857600) play.ws.max-content-length = -1
之后用标准get()方法处理:
request.get().map { response => if (response.status == 200) { val jsonArray = response.json.as[JsArray] // 处理jsonArray } else { // 处理错误状态 } }
代码错误修正点
- 复用WS客户端:
AhcWSClient()创建开销极大,必须复用实例,请求结束后统一关闭; - 移除阻塞操作:
Await.result和Thread.sleep会阻塞线程,破坏Play异步模型,改用flatMap、traverse等Future组合操作; - 禁止同步获取流内容:
bodyAsBytes是阻塞操作,必须用Akka Stream异步Sink收集响应体。
内容的提问来源于stack exchange,提问作者Cameron Burley
相关产品推荐
相关产品推荐

