You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala Play WS获取超长JSON响应不完整问题求助

解决Play框架WS异步调用超长JSON数组响应问题

你遇到的问题根源有两个:

  1. 使用get()方法时,受限于Play WS默认的响应大小限制,导致超长JSON被截断;
  2. 用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:49:13