Spray(3)spray-routing

本文介绍Spray路由模块,一种用于RESTful Web服务的高度灵活的路由DSL。文章演示了如何使用该模块配合Spray-Can HttpServer实现简单的路由应用程序,并讨论了关键概念,包括路由类型、构造路由的方法以及异常处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spray(3)spray-routing


The spray-routing module provides a high-level, very flexible routing DSL for RESTful web services. Normally I will use it either on top of a spray-can HttpServer or inside of a servlet container together with spray-servlet.


Dependencies
spray-http, spray-httpx, spray-util, spray-caching, shapeless, Scalate, akka-actor


"io.spray" % "spray-routing" % "1.1-M7",
"com.typesafe" % "config" % "1.0.0"


Configuration
Just like Akka spray-routing relies on the type safe config library for configuration. The same configuration file with akka, application.conf(reference.conf).


Getting Started
SimpleRoutingApp
package com.sillycat.easyspray.external

import spray.routing.SimpleRoutingApp

import spray.http.MediaTypes._

import scala.concurrent.duration._

object EasyRoutingApp extends App with SimpleRoutingApp {


startServer(interface = "localhost", port = 8080) {

get {

path("") {

redirect("/hello")

} ~

path("hello") {

respondWithMediaType(`text/html`) { // XML is marshalled to `text/xml` by default, so we simply override here

complete {

<html>

<h1>Say hello to <em>spray</em> on <em>spray-can</em>!</h1>

<p>(<a href="/stop?method=post">stop server</a>)</p>

</html>

}

}

}

} ~

(post | parameter('method ! "post")) {

path("stop") {

complete {

system.scheduler.scheduleOnce(1 second span) {

system.shutdown()

}

"Shutting down in 1 second…"

}

}

}

}



}


Key Concepts
Big Picture
We have spray-can HttpServer and the spray-servlet connector servlet both an actor-level to response to incoming HTTP requests by simply replying with an HttpResponse.


We can do complete REST API by pattern-matching against the incoming HttpRequest. But it is not wise to do in that way.


As an alternative spray-routing provides a flexible DSL for expressing service behavior.


def receive = runRoute {

path("ping"){

get{

complete("PONG")

}

}

}


Routes
type Route = RequestContext => Unit


Generally when a route receives a request (or rather a RequestContext for it) it can do one of the three things:

1. Complete the request by calling requestContext.complete(…)

2. Reject the request by calling requestContext.reject(…)

3. Ignore the request


Constructing Routes
ctx => ctx.complete("Response") ----> complete("Response")


Composing Routes
Route transformation, Route filtering, Route chaining


The Routing Tree
varl route =

a{

b{

c{…} ~

d{…} ~

...

} ~

...

}


Directives
val route =
path("order" / IntNumber) { id =>
(get | put) { ctx =>
ctx.complete("Received " + ctx.request.method + " request for order " + id)
} }
Or

val getOrPut = get | put
val route =
(path("order" / IntNumber) & getOrPut) { id => ctx =>
ctx.complete("Received " + ctx.request.method + " request for order " + id) }


Rejections
The ~ operator was introduced, which connects two routes in a way that allows a second route to get a go at a request if the first route "rejected" it.


Exception Handling


import spray.routing.SimpleRoutingApp

import spray.http.MediaTypes._

import scala.concurrent.duration._

import spray.util.LoggingContext

import spray.routing.ExceptionHandler

import spray.util.LoggingContext

import spray.http.StatusCodes._

import spray.routing._


object EasyRoutingApp extends App with SimpleRoutingApp {


implicit def myExceptionHandler(implicit log: LoggingContext) =

ExceptionHandler.fromPF {

case e: ArithmeticException => ctx =>

log.warning("Request {} could not be handled normally", ctx.request)

ctx.complete(InternalServerError, "Bad numbers, bad result!!!")

}

…snip…


Timeout Handling
import spray.http._
import spray.routing._

class MyService extends Actor with HttpServiceActor {
def receive = handleTimeouts orElse runRoute(myRoute)

def myRoute: Route = `<my-route-definition>`

def handleTimeouts: Receive = {
case Timeout(x: HttpRequest) =>
sender ! HttpResponse(StatusCodes.InternalServerError, "Too late")
} }


References:
http://spray.io/documentation/spray-routing/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值