spray 是基于 akka 的轻量级 scala 库,可用于编写 REST API 服务。了解 spray 的 DSL 后可以在很短的时间内写出一个 REST API 服务,它的部署并不需要 tomcat , apche 等容器,可以直接 run。对于每一个 route, spray 都会 sprawn 一个或多个 actor提供服务,actor 的数目是可以配置的,我们不需要关心多线程处理的问题。从 benchmark 来看, spray 的性能是很不错。另外,spray 提供了一套测试套件,testkit,使用它可以在本地测试 API 的可用性,测试功能非常强大,我想它可以完全取代 SoapUI 之类的自动化测试工具

但是,学习使用spray的过程还是比较痛苦的,举个例子

Await.result(statement, 5.seconds)

写下这行代码后,IDE 会抱怨 5.seconds 理解不了,但是它在哪,IDE并不会提示。还有很多情况是,IDE 不会抱怨,但是编译过程会出错,说找不到某个 implicit 变量。接触spray三个月,最让我头疼的就是implicit变量的问题。关于常用的变量的头文件位置,我想写一篇日志记录一下

下面是一些概念性的理解,主要是参考 spray doc,附带部分自己的理解。

Route

type Route = RequestContext => Unit

RequestContext 在 route 里是局部变量,它总是存在的,我们可以在 route 的任何位置调用 RequestContext 的方法。RequestContext 包含     request 和 response 两层含义,既能获得request传过来的数据,也能完成.complete, .reject 等response语义。Route的定义并没有返回值,它的返回值为Unit,这是因为Route 采用的是 fire and forget (tell) 模式,它的好处首先是灵活,没有限制返回值的类型,其次是这种设计是完全的非阻塞的,易于和actor结合

Directive (指令)

spray的 DSL 就是一个个 Directive 拼在一起的

def routes = {
path("") {
get {
respondWithMediaType(`text/html`) {
complete {
DefaultValues.defaultAPI
}
}
}
}
}

path, get, respondWithMediaType, complete 都算是一条 Directive。他们嵌套在一起形成一个 Route 的语义。一般来讲,Directive有四个功能,首先是复制 RequestContext 到下一层 Directive,RequestContext 在传输的过程中是 immutable 的。其次,它可以获取 requester 附带的参数,比如 parameters, formData, jsonData 等,还能完成 marshall, unmarshall 操作。定义路径和某些逻辑来过滤一条请求,比如不符合任意一个 path 的请求将会被 reject,逻辑可以是 header 必须拒绝缓存,post data 只允许 json 格式等等。最后,他可以用返回结果到 requester,可以定义结果的类型和值,在上面的例子上就是 text/html 和 string(defaultAPI)

Reject, Exception, Timeout handling

requester的请求可能格式有错误,可能权限不足,也可能数据包丢失,因此 spray 需要 ”异常“处理。异常处理可以是显式的自定义声明,spray 也有默认的实现。对于那些不符合任何 path(或者符合 reject path), 传输数据出错,没有认证的请求,spray 会调用 reject handling 的实现,程序的执行过程中出现的问题会调用 exception handling定义的操作,比如对于除0异常的处理。 Timeout 最简单,它定义请求在多少时间没有应答就会返回超时错误。

spray 通过 complete(code, message) 实现,浏览器会显示 code, message。对那些比较普遍的错误,spray有自定义的code, message,而那些自定义的错误,我们要手写 code message。

Json support

上面提到directive的四种功能,其中就包括从requestContext中获取parameter和formData。除此之外,spray 还提供从 json 到 case class 的映射,这相当于一个轻量级的 ORM,让我们的逻辑代码写的更加美观。

object Json4sProtocol extends Json4sSupport {
implicit def json4sFormats: Formats = DefaultFormats
}
import models.Json4sProtocol._

json -> case class 有多个库可以选择,我更喜欢 json4s,相比于 spray.json,json4s的mapping更加简单,不需要为每一个case class写一个转换器。此外,json4s来支持json -> case class 的不完全转换,也就是说 json 可以有某些域不存在,但是 case class 对应的那些域必须声明为 Option[]

从 parameter 到 case class 也有映射,

case class Color(keyword: String, sort_order: Int, sort_key: String)

  val testRoute =
path("test") {
parameters('keyword.as[String], 'sort_order.as[Int], 'sort_key.as[String]).as(Color) { color =>
//handleTestRoute(color) // route working with the Color instance
complete {
<h1>test route</h1>
}
}
}

spray test-kit

test-kit 能够实现本地测试 Route,配合 spec2 可以取代 soapUI等自动化测试工具。

"main entrance (/) working" in {
Get("/") ~> routes ~> check {
status === OK
response.entity.asString === DefaultValues.defaultAPI }
}
step {
server.start()
server.createAndWaitForIndex("persons")
} "Elasticsearch person dao" should {
"return None for a non-existing person" in new Context {
val person: Option[Person] = dao.get(UUID.randomUUID)
person must beNone
} "create and then return a person" in new Context {
val id: UUID = dao.add(name = "John")
val person = dao.get(id)
person must beSome[Person]
person must haveName("John")
}
} step {
server.stop()
}

test-kit 支持更丰富的语法糖,比如 beSome, beSome(data)等等,相比于 scalatest,spec2 提供更多的语法糖支持。

scala spray 概念性内容的总结的更多相关文章

  1. Jquery 概念性内容编辑器

      概念性jQuery内容编辑器,这是一款非常有特色的jQuery编辑器,该编辑器支持文字.列表.视频.引用等功能,是一款小巧简洁,富有个性化的jQuery内容编辑器插件. 代码: <!doct ...

  2. 怎样学习Scala泛函编程

    确切来说应该是我打算怎么去学习Scala泛函编程.在网上找不到系统化完整的Scala泛函编程学习资料,只好把能找到的一些书籍.博客.演讲稿.论坛问答.技术说明等组织一下,希望能达到学习目的.关于Sca ...

  3. Scala HandBook

    目录[-] 1.   Scala有多cool 1.1.     速度! 1.2.     易用的数据结构 1.3.     OOP+FP 1.4.     动态+静态 1.5.     DSL 1.6 ...

  4. 使用SBT构建Scala应用(转自git)

    # 使用SBT构建Scala应用 ## SBT简介 SBT是Simple Build Tool的简称,如果读者使用过Maven,那么可以简单将SBT看做是Scala世界的Maven,虽然二者各有优劣, ...

  5. 【原】SBT构建Scala应用

    [转帖] 原文地址:https://github.com/CSUG/real_world_scala/blob/master/02_sbt.markdown 尊重版权,尊重他人劳动成果,转帖请注明原文 ...

  6. Java 8 vs. Scala(一): Lambda表达式

    [编者按]虽然 Java 深得大量开发者喜爱,但是对比其他现代编程语言,其语法确实略显冗长.但是通过 Java8,直接利用 lambda 表达式就能编写出既可读又简洁的代码.作者 Hussachai ...

  7. scala 小结(一)

    Scala 是什么?(What is scala?)   引用百度百科对于scala的定义: Scala是一门多范式的编程语言,一种类似java的编程语言,设计初衷是实现可伸缩的语言.并集成面向对象编 ...

  8. Programming In Scala笔记-第九章、控制抽象

    本章主要讲解在Scala中如何使用函数值来自定义新的控制结构,并且介绍Curring和By-name参数的概念. 一.减少重复代码 1.重复代码的场景描述 前面定义的函数,将实现某功能的代码封装到一起 ...

  9. 使用SBT构建Scala应用【转载】

    使用SBT构建Scala应用 SBT简介 SBT是Simple Build Tool的简称,如果读者使用过Maven,那么可以简单将SBT看做是Scala世界的Maven,虽然二者各有优劣,但完成的工 ...

随机推荐

  1. hbase源码系列(六)HMaster启动过程

    这一章是server端开始的第一章,有兴趣的朋友先去看一下hbase的架构图,我专门从网上弄下来的. 按照HMaster的run方法的注释,我们可以了解到它的启动过程会去做以下的动作. * <l ...

  2. 在Ubuntu 14.04 64bit上安装网易云音乐Linux版本(最新官方版)

    在Chrome浏览器中,登陆官网下载Linux版本中的Ubuntu 16.04 64bit的deb包 http://music.163.com/#/download 下载完成后,双击该deb包即可自动 ...

  3. .NetCore程序发布到IIS上面

    一.概述 在传统的.NET Framework中,ASP.NET程序发布到IIS上面,是由IIS的工作进程(w3wp.exe)托管的,在任务管理器中可以找到该进程.在ASP.NET Core程序中不再 ...

  4. 再谈git的http服务

    因为git服务器搬迁,需要重新安装git服务器,在网上搜索了下,发现之前的方法太复杂,复杂到自己都没彻底弄明白.其实通过git自带的git-http-backend脚本配合apache2的http服务 ...

  5. iOS 实时音频采集与播放Audio Unit使用

    前言 在iOS中有很多方法可以进行音视频采集.如 AVCaptureDevice, AudioQueue以及Audio Unit.其中 Audio Unit是最底层的接口,它的优点是功能强大,延迟低; ...

  6. springmvc搭建环境时报No mapping found for HTTP request with URI [/exam3/welcome] in DispatcherServlet with name 'spring2'

    项目是使用spring MVC (1)在浏览器中访问,后台总报错: No mapping found for HTTP request with URI [/exam3/welcome] in Dis ...

  7. hashMap put方法 第二行代码

    if (table == EMPTY_TABLE) { inflateTable(threshold); } table transient Entry<K,V>[] table = (E ...

  8. Ubuntu之网易云音乐无法启动

    官方最新版(1.1)有这个问题,似乎改成0.9版就可以了 deepin15(32位):http://s1.music.126.net/download/pc/netease-cloud-music_0 ...

  9. Android Error: This attribute must be localized.

    在android中使用mmm命令编译程序是出现错误. 这种问题一般情况是因为在res/xml文件夹下的中, 或者在res/layout下的文件中出现了没有多语言话的文本例. 解决方法: 不直接在布局文 ...

  10. SpringMVC系列(十二)自定义拦截器

    Spring MVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必须实现HandlerInterceptor接口– preHandle():这个方法在业务处 ...