Spray.io搭建Rest服務

Spray.io嘗試 css

使用Spray.io搭建Rest服務

Spray 是一個開源的 REST/HTTP 工具包和底層網絡 IO 包,基於 Scala 和 Akka 構建。輕量級、異步、非堵塞、基於 actor 模式、模塊化和可測試是 spray 的特色。 html

你能夠經過git@osc上面獲取代碼 http://git.oschina.net/for-1988/Simples/tree/master/SpraySimple  java

工程環境

  • IDE: IntelliJ IDEA 13.1.1 (安裝Scala、SBT插件)
  • Spray 1.2, akka 2.2.3 , Scala 2.10.3

SBT配置

build.sbt git

name := "SpraySimple"
version := "1.0"
scalaVersion  := "2.10.3"
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8")

resolvers ++= Seq(
  "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/",
  "Spray repository" at "http://repo.spray.io/"
)

libraryDependencies ++= {
  val akkaV = "2.2.3"
  val sprayV = "1.2.0"
  Seq(
    //"org.java-websocket"  %   "Java-WebSocket" % "1.3.1",
    "org.json4s"    %% "json4s-native"   % "3.2.4",
    "io.spray"            %%  "spray-json"     % "1.2.5",
    "io.spray"            %   "spray-can"      % sprayV,
    "io.spray"            %   "spray-routing"  % sprayV,
    "com.typesafe.akka"   %%  "akka-actor"     % akkaV,
    "com.typesafe.akka"   %%  "akka-testkit"   % akkaV   % "test",
    "io.spray"            %   "spray-testkit"  % sprayV  % "test",
    "org.scalatest"       %%  "scalatest"      % "2.0"   % "test",
    "junit"               %   "junit"          % "4.11"  % "test",
    "org.specs2"          %%  "specs2"         % "2.2.3" % "test"
  )
}

plugins.sbt web

logLevel := Level.Warn

addSbtPlugin("io.spray" % "sbt-revolver" % "0.7.1")
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.1.2")


Spray 啓動web服務

    Spray的Spray-Can模塊來提供web服務,它自己就提供了服務器功能,這樣就無需其餘服務器。啓動Http監聽只須要下面一句代碼 json

IO(Http) ! Http.Bind(httpServer, Configuration.host, port = Configuration.portHttp)

    直接藉助Scala的main方法就能夠啓動。Spray是基於Akka構建的,因此啓動須要基於Akka的ActorSystem。httpServer對象就是一個Akka的Actor。 服務器

    完整的啓動類: websocket

object Server extends App with Routes {
  implicit lazy val system = ActorSystem("server-system")
  lazy val index = system.actorOf(Props[IndexActor], "index")

  implicit lazy val routes = {
    new IndexService(index)(system).route
  }

  IO(Http) ! Http.Bind(httpServer, Configuration.host, port = Configuration.portHttp)
}

object Configuration {

  import com.typesafe.config.ConfigFactory

  private val config = ConfigFactory.load
  config.checkValid(ConfigFactory.defaultReference)

  val host = config.getString("http.server.host")
  val portHttp = config.getInt("http.server.ports.http")
  val portTcp = config.getInt("http.server.ports.tcp")
  val portWs = config.getInt("http.server.ports.ws")
}

Spray的路由

    Spray的spray-routing模塊提供路由功能,上面能夠看到啓動類Server繼承了Routes,這個Trait是咱們本身寫來處理路由部分的代碼,咱們先看下它的實現代碼 java-web

trait Routes extends RouteConcatenation with StaticRoute with AbstractAkkaSystem {

  val httpServer = system.actorOf(Props(classOf[HttpServer], allRoutes))

  implicit def routes: Route


  lazy val allRoutes = logRequest(showReq _) {
    routes ~ staticRoute
  }

  private def showReq(req: HttpRequest) = LogEntry(req.uri, InfoLevel)
}


trait StaticRoute extends Directives {
  this: AbstractAkkaSystem =>

  lazy val staticRoute =
    path("favicon.ico") {
      getFromResource("favicon.ico")
    } ~
      pathPrefix("markers") {
        getFromResourceDirectory("markers/")
      } ~
      pathPrefix("css") {
        getFromResourceDirectory("css/")
      } ~
      pathEndOrSingleSlash {
        getFromResource("index.html")
      } ~ complete(NotFound)
}

AbstractAkkaSystem: 網絡

trait AbstractAkkaSystem {
  implicit def system: ActorSystem
}


這裏咱們初始化了HttpServer對象,並定義了隱式參數routes,還有對靜態資源的路由配置。在Server中,咱們對routes進行了實現,加入了IndexService的實現類。在這個類中,咱們實現了一個很簡單的Rest功能。

HttpServer對象

class HttpServer(route: Route)  extends Actor with HttpService with ActorLogging {

  implicit def actorRefFactory = context

  override def receive = runRoute(route)
}
HttpServer對象實現了spray.routing.HttpService 和akka.actor.Actor,
implicit def actorRefFactory = context    //實現HttpService中的隱式方法 actorRefFactory 


override def receive = runRoute(route)   // 實現Actor的receive方法,交給HttpService中的runRoute處理

路由映射及返回資源處理

class IndexActor extends Actor with ActorLogging {
  override def receive = {
    case None =>
  }
}

class IndexService(index: ActorRef)(implicit system: ActorSystem) extends Directives with Json4sSupport {
  implicit def json4sFormats: Formats = DefaultFormats

  lazy val route =
    pathPrefix("page") {
      val dir = "page/"
      pathEndOrSingleSlash {
        getFromResource(dir + "index.html")
      } ~
        getFromResourceDirectory(dir)
    } ~
      path("echo" / Segment) {
        message => get {
          complete {
            s"${message}"
          }
        }
      } ~
      path("person") {
        get {
          complete {
            val person = new Person("Feng Jiang", 26)
            person
          }
        }
      }
}



這裏添加了三個路由映射,1.打開index.html,2.回顯 ~/echo/{message}  , 3.返回Person對象的json

相關文章
相關標籤/搜索