Spray.io嘗試 css
Spray 是一個開源的 REST/HTTP 工具包和底層網絡 IO 包,基於 Scala 和 Akka 構建。輕量級、異步、非堵塞、基於 actor 模式、模塊化和可測試是 spray 的特色。 html
你能夠經過git@osc上面獲取代碼 http://git.oschina.net/for-1988/Simples/tree/master/SpraySimple java
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的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-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 } } } }