scala spray 概念性内容的总结
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 概念性内容的总结的更多相关文章
- Jquery 概念性内容编辑器
概念性jQuery内容编辑器,这是一款非常有特色的jQuery编辑器,该编辑器支持文字.列表.视频.引用等功能,是一款小巧简洁,富有个性化的jQuery内容编辑器插件. 代码: <!doct ...
- 怎样学习Scala泛函编程
确切来说应该是我打算怎么去学习Scala泛函编程.在网上找不到系统化完整的Scala泛函编程学习资料,只好把能找到的一些书籍.博客.演讲稿.论坛问答.技术说明等组织一下,希望能达到学习目的.关于Sca ...
- Scala HandBook
目录[-] 1. Scala有多cool 1.1. 速度! 1.2. 易用的数据结构 1.3. OOP+FP 1.4. 动态+静态 1.5. DSL 1.6 ...
- 使用SBT构建Scala应用(转自git)
# 使用SBT构建Scala应用 ## SBT简介 SBT是Simple Build Tool的简称,如果读者使用过Maven,那么可以简单将SBT看做是Scala世界的Maven,虽然二者各有优劣, ...
- 【原】SBT构建Scala应用
[转帖] 原文地址:https://github.com/CSUG/real_world_scala/blob/master/02_sbt.markdown 尊重版权,尊重他人劳动成果,转帖请注明原文 ...
- Java 8 vs. Scala(一): Lambda表达式
[编者按]虽然 Java 深得大量开发者喜爱,但是对比其他现代编程语言,其语法确实略显冗长.但是通过 Java8,直接利用 lambda 表达式就能编写出既可读又简洁的代码.作者 Hussachai ...
- scala 小结(一)
Scala 是什么?(What is scala?) 引用百度百科对于scala的定义: Scala是一门多范式的编程语言,一种类似java的编程语言,设计初衷是实现可伸缩的语言.并集成面向对象编 ...
- Programming In Scala笔记-第九章、控制抽象
本章主要讲解在Scala中如何使用函数值来自定义新的控制结构,并且介绍Curring和By-name参数的概念. 一.减少重复代码 1.重复代码的场景描述 前面定义的函数,将实现某功能的代码封装到一起 ...
- 使用SBT构建Scala应用【转载】
使用SBT构建Scala应用 SBT简介 SBT是Simple Build Tool的简称,如果读者使用过Maven,那么可以简单将SBT看做是Scala世界的Maven,虽然二者各有优劣,但完成的工 ...
随机推荐
- mysql ACID与四种隔离级别归纳总结
关于数据库的ACID特性已经有很多的介绍,这里再重新归纳总结一下: A(atomicity)原子性: 即事务要么全部做完,要么全部不做,不会出现只做一部分的情形,如A给B转帐,不会出现A的钱少了, ...
- linq操作符:连接操作符
linq中的连接操作符主要包括Join()和GroupJoin()两个. 一.Join()操作符 Join()操作符非常类似于T-SQL中的inner join,它将两个数据源进行连接,根据两个数据源 ...
- php curl_multi系列函数实现多线程抓取网页
最近几天在做一个多搜索引擎关键字排名查询工具,用于及时方便的了解关键词在各大搜索引擎的排名. 在抓取360搜索的时候,发现360搜索每页只支持显示10个搜索结果,如果想获取100个搜索结果数据,就得搜 ...
- 【CSS3】好玩的动画线框
<div class="box">动画选框</div> .box{ width:300px; height:100px; border:1px dotted ...
- Python 字典的操作
#-*- coding:utf-8 -*- people = {"name":"jack","age":18,"addr" ...
- 自然语言交流系统 phxnet团队 创新实训 个人博客 (六)
讯飞的语音sdk是需要申请的,地址是:http://dev.voicecloud.cn/developer.php?vt=1 .申请一个讯飞的开发者账号,然后申请一个appid,申请的时候需要填写开发 ...
- 关于Unity中RectTransform和Transform
以前一直以为在Inspector面板上的是Transform,后来才发现原来2D是RectTransform,3D是Transform 3D面板上显示的是位置坐标组件Transform,2D面板上显示 ...
- Python之输出当前时间
import time print time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
- MFC绘图基础——上机操作步骤
一.上机之前的介绍 软件环境:VC++6.0 目的:熟悉基本的MFC框架搭建和了解界面 二.MFC上机操作步骤 1,在Windows桌面上运行VC++6.0. 2,新建项目工程文件. 3,在MFC 应 ...
- Type cvc-complex-type.2.4.c: The matching wildcard is strict...
这个问题困扰了我两次,分别说一下原因:1. 如网上一些网友所言,是在配置Spring的标签库的时候有拼写错误或者遗漏.下面贴一个标准3.0的吧: <?xml version="1.0& ...