如何访问Akka Http GET请求的响应数据
Akka HTTP 构造GET请求后获取响应内容的方法
给出的两种构造GET请求的示例代码如下:
HttpRequest(uri = "https://akka.io") // 或者引入快捷构造方法 import akka.http.scaladsl.client.RequestBuilding.Get Get("https://akka.io")
要实现和io.Source.fromURL(url).mkString等效的效果,直接拿到请求返回的完整文本,要注意Akka HTTP是基于响应式流实现的全异步HTTP客户端,所有请求、响应操作都是非阻塞的,没法直接同步拿到返回值,按下面的流程写即可。
第一步:初始化运行依赖
Akka HTTP 必须依赖Actor系统和流物化器才能运行,先定义好隐式实例:
import akka.actor.ActorSystem import akka.http.scaladsl.Http import akka.http.scaladsl.model._ import akka.stream.ActorMaterializer import scala.concurrent.Await import scala.concurrent.duration._ import akka.http.scaladsl.client.RequestBuilding.Get implicit val actorSystem: ActorSystem = ActorSystem() implicit val materializer: ActorMaterializer = ActorMaterializer() import actorSystem.dispatcher
第二步:实现和Source.fromURL完全等效的同步方法
io.Source.fromURL是同步阻塞调用,我们可以通过等待异步结果的方式对齐行为,注意要把流式的响应实体转换成可直接读取的完整内容:
def getUrlContent(url: String, requestTimeout: Duration = 10.seconds): String = { val future = Http() .singleRequest(Get(url)) .flatMap { resp => // 非2xx状态直接抛错,和Source.fromURL的错误行为对齐 if (!resp.status.isSuccess()) { resp.discardEntityBytes() throw new RuntimeException(s"请求异常,状态码:${resp.status}") } // 把分块传输的流式响应收集为完整字节块 resp.entity.toStrict(requestTimeout).map(_.data.utf8String) } // 阻塞等待结果,实现和同步调用一致的效果 Await.result(future, requestTimeout + 3.seconds) }
调用方式和原来的逻辑完全一致:
val content = getUrlContent("https://akka.io") println(content)
生产环境推荐非阻塞写法
同步阻塞会占用线程资源,线上环境建议直接处理异步返回的Future,不要硬等结果:
Http() .singleRequest(Get("https://akka.io")) .flatMap(resp => resp.entity.toStrict(10.seconds)) .map(entity => println(s"返回内容长度:${entity.data.length}")) .andThen { case _ => // 操作结束后关闭Actor系统释放资源,否则程序不会正常退出 actorSystem.terminate() }
注意点
- 不管是否需要读取响应内容,如果不消费实体字节,一定要调用
discardEntityBytes()丢弃,否则会造成连接池泄漏 toStrict的超时时间根据实际接口响应速度调整,大响应体可以适当拉长超时- 程序退出前记得终止ActorSystem,否则后台线程会一直存活
内容的提问来源于stack exchange,提问作者DJames
相关产品推荐
相关产品推荐

