spray-routing - 路由

原创
2013/04/08 12:24
阅读数 697

spray.io的文档太晦涩,啃起来太痛苦了。还有,屋里真冷。
路由

“路由”是spray-routing的中心概念,因为所有你用DSL创建的结构都是Route的子类型。在spray-routing中一个路由需要如下方式定义:

type Route = RequestContext => Unit

它是一个把RequestContext作为参数的函数的别名。

不同于你最初所期望的,一个路由不返回任何东西。相反,所有响应处理(在路由处理完一个请求后需要完成的所有事情)是通过 RequestContext的响应器来执行的(in “continuation-style”)。如果你不知道这意味着什么的话,别担心。这些很快就会变得清晰。关键是,这种设计的优点是完全非阻塞以及 Actor友好的,因为这种方式,它可以简单地把一个RequestContext发送给另一个Actor(以“fire-and-forget”的方 式),而不必担心结果处理。

通常当一个路由接收到一个请求(或者说是一个RequestContext)它可以做这三件事中的一个:

  • 通过调用requestContext.complete(...)完成这个请求
  • 通过调用requestContext.reject(...)拒绝这个请求
  • 忽略这个请求(既不完成也不拒绝)

第一种情况相当清楚,通过调用complete将一个给定的响应发送到客户端作为这个请求的反应。第二种情况中,“拒绝”意味着路由不想处理这个请 求。You’ll see further down in the section about route composition what this is good for。第三种情况通常是一个错误。如果一个路由对请求不做任何事情,它会简单的不对它产生作用。这意味着客户端将接收不到响应,直到请求超时,此时会生 成一个“500 Internal Server Error ”响应。因此你的路由通常以完成或拒绝请求来结束。

构造路由

路由是普通的函数(RequestContext => Unit),最简单的路由是:

ctx => ctx.complete("Response")

更简短的:

_.complete("Response")

还有更短的(用complete指令):

complete("Response")

这些都是不同的方式定义相同的东西,即一个路由用一个静态响应简单地完成所有请求。

虽然你可以把所有应用逻辑写到一个函数里,来检查RequestContext并根据它的属性来完成它,但这种设计很难阅读,维护和重用。因此spray-routing允许你通过组合简单的路由来构造更复杂的路由。

组合路由

用简单路由构造复杂路由有三个基本的操作:

  • 路由转换,which delegates processing to another, “inner” route but in the process changes some properties of either the incoming request, the outgoing response or both(什么意思???)
  • 路由过滤,只允许满足给定过滤器条件的请求通过,并拒绝其他所有的
  • 路由链,如果第一个路由拒绝了,它会尝试第二个

最后一点通过简单的~操作来完成,它对所有路由都有效,例如一个隐式的“扩展”。前两点由Directives来提供,spray-routing已经预定义了大多数,你也可以自己简单地创建。Directives给予spray-routing大部分能力和灵活性。

路由树

基本上,当你通过嵌套和~操作来结合指令和自定义路由时,你构造了一个树形路由结构。当一个请求到来,它被注入到树的根,并以深度优先的方式向下流经所有分支,直到有节点完成,或全部拒绝。

考虑这个例子:

val route =
  a {
    b {
      c {
        ... // route 1
      } ~
      d {
        ... // route 2
      } ~
      ... // route 3
    } ~
    e {
      ... // route 4
    }
  }
有5个构成路由树的指令。
  • 路由1仅在指令a,b和c都通过时可达。
  • 如果a,b通过,c拒绝并且d通过,将运行路由2。
  • 如果a和b通过,但c和d拒绝,将运行路由3。

路由3因此可以被视为一种“全方位”路由(如果路由链接前面的位置拒绝)。这种机制可以使复杂的过滤逻辑很容易实现:简单地把最具体的情况提前并把一般情况放后面。

展开阅读全文
打赏
1
2 收藏
分享
加载中
路由转换,which delegates processing to another, “inner” route but in the process changes some properties of either the incoming request, the outgoing response or both
路由转换,将处理委托给另一个路由,“内部”路由但是在这个过程中改变了一些属性,或者是进来的请求,或只是发出的响应,或者两者都有。直译的,应该就是这意思吧
2015/09/21 10:22
回复
举报
更多评论
打赏
1 评论
2 收藏
1
分享
在线直播报名
返回顶部
顶部