`
sillycat
  • 浏览: 2566888 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Spray(2)spray-can

 
阅读更多
Spray(2)spray-can


Prepare the Sample codes
>git clone https://github.com/spray/spray.git

>cd spray



And we can run both the 2 examples like this:

>sbt "project simple-http-client" run

>sbt "project simple-http-server" run



Everything runs fine, I will import the project into eclipse

>sbt update

>sbt eclipse



And I import these projects to my eclipse

simple-http-server

spray-can

spray-http

spray-io

spray-util



Go through the Online Documents to understand spray-can
Dependencies
spray-can depends on spray-io, spray-http, spray-util, akka-actor.



Create a learning project under easy sub system

>mkdir easyspray

>cd easyspray

>vi build.sbt

name := "easyspray"



organization := "com.sillycat"



version := "1.0"



scalaVersion := "2.10.0-RC1"



scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8")



>sbt update

>sbt eclipse



Import my sample project into eclipse.



Installation
I already have a sbt project named easyspray, and I will install spray-can in that project.



make the resolvers in sbt as follow:

resolvers ++= Seq(

     "sonatype releases"  at "https://oss.sonatype.org/content/repositories/releases/",

     "sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/",

   "typesafe repo"      at "http://repo.typesafe.com/typesafe/releases/",

   "spray repo"         at "http://repo.spray.io/"

)



Add the sbt maven dependencies like this>

libraryDependencies ++= Seq(

     "io.spray"            %   "spray-io"                  % "1.1-M4",
          "io.spray"                  %   "spray-http"                                % "1.1-M4",
     "io.spray"            %   "spray-can"                 % "1.1-M4",
     "io.spray"            %   "spray-util"                % "1.1-M4",
     "com.typesafe.akka"   %%  "akka-actor"                % "2.1.0-RC1"   cross CrossVersion.full,
     "com.typesafe"        %   "config"                    % "1.0.0"

)



The most important configuration file is
reference.conf configure the server side configuration and database connection configuration.


HttpServer
Connection management

Message parsing and header separation

Timeout management

Response ordering



Basic Architecture
The spray-can HttpServer is implemented as an Akka actor, which talks to an underlying IOBridge and spawns new child actors for every new connection.



Just receive the request, and design in which case it will go, sender it to the handler when response the html.

def receive = {

    case HttpRequest(GET, "/", _, _, _) =>

      sender ! index

}



lazy val index = HttpResponse(

    entity = HttpBody(`text/html`,

      <html>

        <body>

          <h1>Say hello to <i>spray-can</i>!</h1>

          <p>Defined resources:</p>

          <ul>

            <li><a href="/ping">/ping</a></li>

            <li><a href="/stream">/stream</a></li>

            <li><a href="/server-stats">/server-stats</a></li>

            <li><a href="/io-stats">/io-stats</a></li>

            <li><a href="/crash">/crash</a></li>

            <li><a href="/timeout">/timeout</a></li>

            <li><a href="/timeout/timeout">/timeout/timeout</a></li>

            <li><a href="/stop">/stop</a></li>

          </ul>

        </body>

      </html>.toString

    )

)



Starting and Stopping
The HttpServer is a regular actor, it starts like this
// the handler actor replies to incoming HttpRequests

val handler = system.actorOf(Props[DemoService])



// create a new HttpServer using our handler and tell it where to bind to

newHttpServer(handler) ! Bind(interface = "localhost", port = 8080)



It stops like this:
context.system.scheduler.scheduleOnce(1 second span, new Runnable { def run() { context.system.shutdown() } })



I think probably this command statement will shutdown the actor  context.system.shutdown(), other codes are just try to schedule that.


Message Protocol
A running HttpServer actor understands the following command messages.
Bind
Start listening for incoming connections on a particular port.


Unbind
Revert a previous Bind.


GetStats


ClearStats


…snip…
SprayCanHttpServerApp trait
I found that I am using the latest sample codes, so I need to change my version from 1.1-M4 to 1.1-M7. So the latest version make SprayCanHttpServerApp trait work.



package com.sillycat.easyspray.external



import spray.can.server.SprayCanHttpServerApp

import akka.actor.Props



object Server extends App with SprayCanHttpServerApp {

  val handler = system.actorOf(Props[EasyRouter])

  newHttpServer(handler) ! Bind(interface = "localhost", port = 8080)

}



package com.sillycat.easyspray.external



import akka.actor.Actor

import spray.http.HttpMethods

import spray.http.HttpRequest

import spray.http.HttpResponse

import spray.util.SprayActorLogging

import spray.http.HttpBody

import spray.http.MediaTypes._



class EasyRouter extends Actor with SprayActorLogging {



  def receive = {

    case HttpRequest(HttpMethods.GET, "/", _, _, _) =>

      sender ! index

  }



  lazy val index = HttpResponse(

    entity = HttpBody(`text/html`,

      <html]]>

        <body]]>

          <h1]]>Welcome Page</h1]]>

        </body]]>

      </html]]>.toString))

}



HttpClient
…snip…


HttpDialog
…snip…


Examples
Example for stop the server and get status from the server:
package com.sillycat.easyspray.external



import scala.concurrent.duration._

import akka.pattern.ask

import akka.util.Timeout

import akka.actor._

import spray.io.{IOBridge, IOExtension}

import spray.can.server.HttpServer

import spray.util._

import spray.http._

import HttpMethods._

import MediaTypes._



class EasyRouter extends Actor with SprayActorLogging {

  implicit val timeout: Timeout = Duration(1, "sec")



  def receive = {

    case HttpRequest(HttpMethods.GET, "/", _, _, _) =>

      sender ! index

    case HttpRequest(HttpMethods.GET, "/stop", _, _, _) =>

      sender ! HttpResponse(entity = "Shutting down in 1 second ...")

      context.system.scheduler.scheduleOnce(1 second span, new Runnable { def run() { context.system.shutdown() } })

    case HttpRequest(GET, "/server-stats", _, _, _) =>

      val client = sender

      (context.actorFor("../http-server") ? HttpServer.GetStats).onSuccess {

        case x: HttpServer.Stats => client ! statsPresentation(x)

      }



    case HttpRequest(GET, "/io-stats", _, _, _) =>

      val client = sender

      (IOExtension(context.system).ioBridge() ? IOBridge.GetStats).onSuccess {

        case IOBridge.StatsMap(map) => client ! statsPresentation(map)

      }

  }



  lazy val index = HttpResponse(

    entity = HttpBody(`text/html`,

      <html>

        <body>

          <h1>Welcome Page</h1>

      <ul>

    <li><a href="/stop">Stop The Server</a></li>

    <li><a href="/server-stats">Server Status</a></li>

    <li><a href="/io-stats">IO Status</a></li>

          </ul>

        </body>

      </html>.toString))

     

  def statsPresentation(s: HttpServer.Stats) = HttpResponse(

    entity = HttpBody(`text/html`,

      <html>

        <body>

          <h1>HttpServer Stats</h1>

          <table>

            <tr><td>uptime:</td><td]]>{s.uptime.formatHMS}</td></tr>

            <tr><td>totalRequests:</td><td>{s.totalRequests}</td></tr>

            <tr><td>openRequests:</td><td>{s.openRequests}</td></tr>

            <tr><td>maxOpenRequests:</td><td>{s.maxOpenRequests}</td></tr>

            <tr><td>totalConnections:</td><td>{s.totalConnections}</td></tr>

            <tr><td>openConnections:</td><td>{s.openConnections}</td></tr>

            <tr><td>maxOpenConnections:</td><td>{s.maxOpenConnections}</td></tr>

            <tr><td>requestTimeouts:</td><td>{s.requestTimeouts}</td></tr>

            <tr><td>idleTimeouts:</td><td>{s.idleTimeouts}</td></tr>

          </table>

        </body>

      </html>.toString

    )

  )

 

  def statsPresentation(map: Map[ActorRef, IOBridge.Stats]) = HttpResponse(

    entity = HttpBody(`text/html`,

      <html>

        <body]]>

          <h1]]>IOBridge Stats</h1]]>

          <table]]>

            {

              def extractData(t: (ActorRef, IOBridge.Stats)) = t._1.path.elements.last :: t._2.productIterator.toList

              val data = map.toSeq.map(extractData).sortBy(_.head.toString).transpose

              valheaders = Seq("IOBridge", "uptime", "bytesRead", "bytesWritten", "connectionsOpened", "commandsExecuted")
              headers.zip(data).map { case (header, items) =>

                <tr><td]]>{header}:</td]]>{items.map(x => <td]]>{x}</td]]>)}</tr]]>

              }

            }

          </table]]>

        </body]]>

      </html]]>.toString

    )

  )

}



References:
http://spray.io/documentation/spray-routing/

http://spray.io/documentation/spray-can/#spray-can

http://sillycat.iteye.com/blog/1744082

http://sillycat.iteye.com/blog/1750374

http://www.scala-sbt.org/release/docs/Getting-Started/index.html



http://spray.io/project-info/maven-repository/


分享到:
评论

相关推荐

    spray-template

    在实际使用中,`spray-template-on_spray-can_1.3`可能是一个包含spray-template特定版本的库,用于与spray-can 1.3版兼容。这个压缩包文件可能包含了以下内容: - `spray-template`的Scala源码或编译后的JAR文件,...

    Docker-Spray-HttpServer:用 Akka + Spray(spray-can)框架编写的一个简单的 Dockerized http 服务器

    Docker-Spray-HttpServer概括Docker Hub 中的仓库名称: 该存储库包含 Dockerized ,通过自动构建机制发布到公共 。 该应用程序主要用作评估 + 框架性能的基准目标。配置此 docker 映像包含以下软件堆栈: 操作系统...

    akka-spray-demo:一个学习AKKA和Spray的演示

    喷雾罐,Scala 2.9 + Akka 2.0 +喷雾1.0( on_spray-can_1.0分支) 喷雾罐,Scala 2.10 + Akka 2.1 +喷雾1.1( on_spray-can_1.1分支) 喷雾罐,Scala 2.10 + Akka 2.2 +喷雾1.2( on_spray-can_1.2分支) 喷雾罐...

    scala-spray-demo

    它包括两个主要部分:一是spray-can,提供了一个异步非阻塞的HTTP服务器容器;二是spray-routing,提供了声明式路由构造器,使构建RESTful服务变得简单直观。在Scala-Spray-Demo中,Spray框架被用来构建RESTful API...

    Paricle System:The Ocean Spray in Your Face

    粒子系统在计算机图形学领域扮演着至关重要的角色,它们能够实时地创造出生动逼真的自然现象,例如海洋的浪花、火光、烟雾、星系等。这背后的关键技术,便是通过模拟无数个微小粒子的行为来构建复杂的视觉效果。...

    netty-socketio-1.6.3.zip

    在使用这个项目时,开发者需要对Java、Netty、Socket.IO以及Scala(因为spray-can是用Scala编写的)有一定的了解。首先,要确保环境中已经安装了JDK和Scala,然后通过Git克隆项目到本地,使用Maven或Gradle等构建...

    hecate-testing-1.0.24.zip

    3. **spray框架**:包括spray-can(HTTP服务器组件)、spray-routing(构建路由的DSL)、spray-client(HTTP客户端)等,它们共同为创建高效的HTTP服务提供了一整套解决方案。 4. **swagger规范**:Swagger定义了一...

    用于大规模的生产部署Squbs.zip

    Spray doesn't have friendly API for Java, the spray.japi package provides a few of Helpers and Factories to help Java developers to construct spray entities easily. Validation provides ...

    信息安全_数据安全_eu-16-Sintsov-Pen-Testing-Vehicl.pdf

    尽管他并非硬件或汽车专家,但他的背景包括JIT-SPRAY、shellcodes、ROP、BoF和Web安全技术,这些知识现在被应用于汽车行业。他参与创建的#CarPWN社区聚集了一群来自俄罗斯的汽车黑客和爱好者,他们热衷于研究汽车...

    CJSpider:抓取一些学校网站的信息

    2. **AKKA框架**:AKKA是基于Actor模型的并发处理库,由Lightbend公司(前身为Typesafe)开发。在CJSpider中,AKKA用于处理分布式系统中的通信问题。Actor模型允许并发执行,每个Actor都有自己的状态和邮箱,通过...

    kebs:Scala库消除样板

    5. **spray-can和akka-http的集成**:kebs库可以与spray-can和akka-http这两个流行的Scala HTTP服务器库无缝集成,简化了HTTP请求处理的实现。 6. **类型安全的属性验证**:kebs还提供了属性验证的功能,允许开发者...

    Building.applications.with.Scala.epub

    However, creating an app in Scala can get a little tricky because of the complexity. This book will help you dive straight into app development by creating a real, reactive, and functional ...

    C# Winform画图板 ,实现图片的打开/保存/文字绘制/矩形/圆形/椭圆形

    5. **喷枪(Spray Can)**: - 喷枪工具通常模仿绘画中的喷漆效果,需要创建一个自定义的绘图算法。可以使用`Graphics`的`DrawLines()`方法或`DrawCurve()`方法,结合一定的随机性和密度来实现。 6. **曲线绘制**...

    scala-rest-client-evaluation:评估scala的其余客户端框架

    - **spray-can**: 是spray工具集的一部分,用于构建高性能的HTTP服务器和客户端,基于Akka。 - **Sttp**: 一个现代、可扩展的HTTP客户端库,支持多种后端,如Java的HttpURLConnection或Akka HTTP。 - **Finch**: ...

    UWS2.1.0.unitypackage

    Based on the recent oceanographic research, can simulate hundreds of thousands of waves with excellent foam and particle spray simulation adding a lot of realism to storm and windy weather. UWS is ...

    New method for measuring diesel nozzle orif ice inlet structures based on synchrotron X-ray tomography

    Based on the synchrotron radiation X-ray tomography technique, the 3D digital models of nozzle tips can be constructed. A new automatic method is presented to reveal the inlet structures accor

Global site tag (gtag.js) - Google Analytics