文档章节

Akka HTTP 快速上手

羊八井
 羊八井
发布于 2017/04/13 10:20
字数 1425
阅读 132
收藏 0

Akka Http 是Akka社区提供的一个 Http服务端/客户端通用工具包,支持 Http 1.0/1.1标准及WebSocket,现在 Http 2 的支持也在紧锣密鼓的实现中。

这篇文章将介绍Akka HTTP Server,我们将介绍Akka Http的常用功能模块及使用方式。Akka Http提供了一套强大、易用、易扩展的route dsl来构建路由。Akka Http Client因还不支持超时功能,现在不建议在产品中使用。

本文代码:akka-http-starter

第一个服务

我们可以从官方提供的 HttpApp 特质开始,它提供了快捷的方式来启动一个Akka HTTP Server。

class WebServer extends HttpApp {
  def route: Route =
    path("hello") {
      get {
        import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._
        complete(<h1>Say hello to akka-http</h1>)
      }
    }
}

path("hello")定义了一个HTTP访问路由,get代表这个路由提供了GET请示,而complete涵数允许我们提供响应结果来完成这个路由定义,这里我们返回了一段文本。Akka Http的路由看起来向声明式的,以一直新颖而又直观的方式来定义HTTP服务。

用户第一次接触这种涵数套涵数(又像树型结构)的代码方式可能不大习惯,其实我们可以换种方式来实现这段代码:

  def traditionRoute: Route = {
    val respResult = complete("result") // 响应结果
    val hPath = path("hello") // 绑定的HTTP访问路径
    hPath(get(result)) 
  }

路径(Http方法(结果)),我们用Java式的风格来实现同样的功能。这样是不是更符合你对代码的预期?

让我们来启动服务:

{% codeblock StartBoot01.scala lang:scala https://github.com/yangbajing/akka-action/blob/master/akka-http-starter/src/main/scala/starter/akka/http/demo01/StartBoot01.scala StartBoot01.scala %} object StartBoot01 { def main(args: Array[String]): Unit = { val server = new WebServer server.startServer("0.0.0.0", 8888) } } {% endcodeblock %}

通过curl命令来测试下我们的第一个Akka HTTP服务(-i选项可以打印HTTP响应头):

curl -i http://localhost:8888/hello
HTTP/1.1 200 OK
Server: akka-http/10.0.5
Date: Fri, 31 Mar 2017 17:05:12 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 31

<h1>Say hello to akka-http</h1>

Route

Akka HTTP 提供了一个灵活的DSL,它有很多可组合的元素(Directive 指令)以简洁、易读的方式来构建服务。 让我们来看下面这个示例:

  path("book") {
    get {
      parameters('name.as[Option[String]], 'isbn.as[Option[String]], 'author.as[Option[String]]) {
        (maybeName, maybeIsbn, maybeAuthor) =>
          complete(s"name: $maybeName, isbn: $maybeIsbn, author: $maybeAuthor")
      }
    }
  }

对于上面这个定义,类似的 Play 路由定义如:

GET  /book controller.Page.book(name: Option[String], isbn: Option[String], author: Option[String)

我们可以看到,对一个API路由的定义拆成了几个函数嵌套的形式。path指定访问路径,get决定这个API提供HTTP GET服务,parameters可以抽取请求参数,而complete将一个字符串返回给前端。

JSON

现在大部分的服务都提供JSON格式的数据,Akka HTTP提供了 Mashaller/Unmashaller机制,用户可以基于此灵活的定制自己的序列化/反序列化方式。这里我们使用 Jackson 来解析/处理 JSON。

首选,我们实现自定义的 Mashaller/Unmashaller:

{% codeblock JacksonSupport.scala lang:scala https://github.com/yangbajing/akka-action/blob/master/akka-http-starter/src/main/scala/starter/akka/http/json/JacksonSupport.scala JacksonSupport.scala %} trait JacksonSupport {

private val jsonStringUnmarshaller = Unmarshaller.byteStringUnmarshaller .forContentTypes(MediaTypes.application/json) .mapWithCharset { case (ByteString.empty, _) => throw Unmarshaller.NoContentException case (data, charset) => data.decodeString(charset.nioCharset.name) }

// HTTP entity => A implicit def unmarshaller[A]( implicit ct: ClassTag[A], objectMapper: ObjectMapper = Jackson.defaultObjectMapper ): FromEntityUnmarshaller[A] = jsonStringUnmarshaller.map( data => objectMapper.readValue(data, ct.runtimeClass).asInstanceOf[A] )

// A => HTTP entity implicit def marshaller[A]( implicit objectMapper: ObjectMapper = Jackson.defaultObjectMapper ): ToEntityMarshaller[A] = { JacksonHelper.marshallerA }

} {% endcodeblock %}

实现自定义的 Marshaller/Unmarshaller 后,我们就可以在 Akka HTTP 中提供 Json 支持了。

{% codeblock PageRoute.scala lang:scala https://github.com/yangbajing/akka-action/blob/master/akka-http-starter/src/main/scala/starter/akka/http/route/PageRoute.scala PageRoute.scala %} import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import starter.akka.http.json.JacksonSupport._

case class PageInput(title: String, content: String)

class PageRoute {

def route: Route = path("page") { post { entity(as[PageInput]) { pageInput => complete(pageInput) } } }

} {% endcodeblock %}

Akka HTTP使用了Scala的隐式转换特性来自定义数据序列化,这是一个非侵入式的设计,用户可以在每个模块选择自己的数据序列化方式。

Route类型

Route 是 Akka HTTP 路由 DSL 里的核心概念,用它构建的所有结构,不管是一条线还是很多条线组成,它们都会是这个类型的实例。

type Route = RequestContext => Future[RouteResult]

组合路由

Akka HTTP 提供3个基本的操作来让我们创建更复杂的路由链:

  1. 路由转换:它代理一个“内部”的路由,并在这个过程中改变一些请求传入的属性,然后传出响应或两者。
  2. 路由过滤:只允许满足给定条件的请求被传递,并拒绝所有其它访问请求。
  3. 路由链:如果第一个请求被拒绝,将尝试第二个路由。使用 ~ 操作符连接多个路由定义。

Akka HTTP 实现了很多默认的指令 akka.http.scaladsl.server.Directives._ ,你也可以很轻松地创建自己的指令。指令提供了强大和灵活的方式来构建 Akka HTTP。

路由树

当通过嵌套和操作符组合指令和自定义路径时,将构建一个路由结构并形成一颗树。当一个 HTTP 请求进来,它将从根进行这颗树,并以深度优先的方式流过所有分支,直到某个节点完成或全部被拒绝为止。

val route =
  a {
    b {
      c {
        ... // route 1
      } ~
      d {
        ... // route 2
      } ~
      ... // route 3
    } ~
    e {
      ... // route 4
    }
  }

这里由5个指令构建了一个路由树:

  1. 当 a, b, c都通过,才到到达路由 1
  2. 当 a 和 b 通过,但 c 被拒绝且 d 通过,将到达路由 2
  3. 当 a 和 b 通过,但 c 和 d 被拒绝,路由 3 被到达

若路由 3 前面的请求都被拒绝,则它将“捕获”所有请求。这个机制使复杂的过滤逻辑可以很容易的实现。把简单和最具体的放在顶端,一般和普通的放到最后。

© 著作权归作者所有

羊八井

羊八井

粉丝 93
博文 41
码字总数 51095
作品 0
朝阳
技术主管
私信 提问
分布式爬虫--CrawlerDemon

CrawlerDemon 是垂直应用爬虫,基于akka+okHttp+spring+jsoup ,配置简单,上手容易,支持配置动态参数,动态代理,http自动重试。 特点 基于 akka 高性能分布式框架 使用 spring 配置请求参...

demon
2015/10/14
2.5K
0
Scala Web开发-Akka HTTP中使用JSON

Jackson Jackson 是Java生态圈里最流行的JSON序列化库,它的官方网站是:https://github.com/FasterXML/jackson。 为什么选择 Jackson 为什么选择 Jackson 而不是更Scala范的 play-json、 ci...

羊八井
2018/10/09
544
0
在Scala中构建Web API的4大框架

Scala是一种强大的语言,很快就成为许多开发人员的最爱。然而,语言只是一个起点-并非每个函数都将由语言核心覆盖。Scala还创建了一些厉害的框架。接下来看看Scala的4个强大框架以及其优点和...

数据星河
2018/11/15
14
0
Scala开发者的Spring-Boot快速上手指南 01

做为一个Scala爱好者,是很想基于 Lightbend 的一套架构进行软件开发的。Play,Akka,Scala,Spark……。不过理想很丰满,现实却很骨感。鉴于那批原教旨主义者,他们对 Spring 已经疯狂迷恋,...

羊八井
2016/03/04
1K
2
Akka框架基本要点介绍

Akka基于Actor模型,提供了一个用于构建可扩展的(Scalable)、弹性的(Resilient)、快速响应的(Responsive)应用程序的平台。本文基本上是基于Akka的官方文档(版本是2.3.12),通过自己的...

东风125
2015/11/28
169
2

没有更多内容

加载失败,请刷新页面

加载更多

jquery底层函数-jQuery.ajaxSetup()

jQuery.ajaxSetup( options )返回: 描述: 为以后要用到的Ajax请求设置默认的值 添加的版本: 1.1jQuery.ajaxSetup( options ) options 类型: PlainObject 一个用来配置Ajax请求的"{键:值}"对,......

前端老手
24分钟前
3
0
Qt编写自定义控件56-波浪曲线

一、前言 波浪曲线控件,其实是之前一个水波进度条控件的一个核心,其实就是利用正弦曲线来生成对应的坐标进行绘制,把这个功能单独提取出来,是为了更详细的研究各种正弦余弦等拓展效果,当...

飞扬青云
30分钟前
3
0
深入理解计算机系统cp1:存储单位与编码

摘要: 理解计算机是如何存储数据的。 原文:深入理解计算机系统cp1:存储单位与编码 作者:Chor Fundebug经授权转载,版权归原作者所有。 1. 存储单位 位:即 bit,表示二进制位,要么是 0 ...

Fundebug
33分钟前
3
0
Python查询比特币实时价格

在本文中我们将学习如何使用使用coinmarketcap提供的比特币行情API,编写Python程序来获取像比特币、莱特币或以太币之类的区块链数字货币的实时行情/实时价格。 1、比特币行情API调用代码 我...

汇智网教程
今天
8
0
爬虫平台Crawlab核心原理--自动提取字段算法

⚠注意: 可配置爬虫现在仅在Python版本(v0.2.1-v0.2.4)可用,在最新版本Golang版本(v0.3.0)还暂时不可用,后续会加上,请关注近期更新 背景 实际的大型爬虫开发项目中,爬虫工程师会被要...

tikazyq
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部