首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Spray(五)REST API Project - Recall and Prepare Project

2013-07-04 
Spray(5)REST API Project - Recall and Prepare ProjectSpray(5)REST API Project - Recall and Prepare

Spray(5)REST API Project - Recall and Prepare Project
Spray(5)REST API Project - Recall and Prepare Project

1. Recall some ideas
These things consist of all the modules we are using.
spray-can, spray-routing, spray-io, spray-http, spray-util, spray-testkit, spray-json

How we deal with HTTP
  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", _, _, _) =>
      valclient = sender
      (context.actorFor("../http-server") ? HttpServer.GetStats).onSuccess {
        casex: HttpServer.Stats => client ! statsPresentation(x)
      }

    case HttpRequest(GET, "/io-stats", _, _, _) =>
      valclient = sender
      (IOExtension(context.system).ioBridge() ? IOBridge.GetStats).onSuccess {
        case IOBridge.StatsMap(map) => client ! statsPresentation(map)
      }
    case HttpRequest(HttpMethods.GET, "/event", _, _, _) =>
      sender ! ok

  }

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")
  } }

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.

Spray-json
Then I can parse the string to AST abstract Syntax Tree(AST).
1.1. String to AST
  valjson1 = """{ "streetNumber": "A1", "street" : "Main Street", "city" : "Colombo" }"""
  valjson2 = """{ "name" : "John", "age" : 26,  "sex" : 0 , "address" : { "streetNumber": "A1", "street" : "Main Street", "city" : "Colombo" }}"""

  //string to AST
  valaddressAST = json1.asJson //or JsonParser(source)
  valpersonAST = json2.asJson

1.2. AST to String
  //AST to string
  println(addressAST.compactPrint) //or .compactPrint
  println(personAST.prettyPrint)

1.3. AST to Object
  import AddressJsonProtocol._
  //AST 2 Object
  val address1 = addressAST.convertTo[Address]

1.4. Object to AST
  //Object 2 AST
  valaddressAST2 = address1.toJson


Slick
Do with slick and native SQL.

2. Prepare a New Project
I need to add something to build.sbt to make some sbt commands works.
sbt>re-start
sbt>re-stop
sbt>assembly

build.sbt
import AssemblyKeys._
seq(Revolver.settings: _*)


mainClass in assembly := Some("com.sillycat.easysprayrestserver.Boot")

artifact in (Compile, assembly) ~= { art =>
  art.copy(`classifier` = Some("assembly"))
}

excludedJars in assembly <<= (fullClasspath in assembly) map { cp =>
  cp filter {_.data.getName == "parboiled-scala_2.10.0-RC1-1.1.3.jar"}
}


addArtifact(artifact in (Compile, assembly), assembly)

Do remember to change the mainClass in assembly.

project/build.properties
sbt.version=0.12.1

project/Build.scala
import sbt._
import Keys._

object ApplicationBuild extends Build {

  lazyvalmain = Project(id = "easysprayrestserver",
    base = file("."), settings = Project.defaultSettings).settings()

}


project/plugins.sbt
addSbtPlugin("io.spray" % "sbt-revolver" % "0.6.2")

addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")


addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.8.5")

Then we can do the command like this
Start the application with default configuration
sbt>re-start

Stop the application
sbt>re-stop

Build the binary file
sbt>assembly

Run the application directly from Java
>java -Dconfig.file=/path/application.conf -jar LocalpointAPI-assembly-0.1.jar

And there is another configuration file.
src/main/resources/application.conf
build.env = ""
build.env = ${?env}
server {
address = "0.0.0.0"
    port = 9000
}environment {app1 {     server {          address = "0.0.0.0"          port = 9001     }}
app2 {     server {          address = "0.0.0.0"          port = 9002     }}

}

The application which will use this configuration will be
  val config = ConfigFactory.load()
  val env = config.getString("build.env")
  var serverAddress: String = config.getString("server.address")
  var serverPort: Int = config.getInt("server.port")

  if (env != null && env != "") {
    serverAddress = if (config.getString("environment." + env + ".server.address") != null) config.getString("environment." + env + ".server.address") elseserverAddress
    serverPort = if (config.getInt("environment." + env + ".server.port") != 0) config.getInt("environment." + env + ".server.port") elseserverPort
  }


  newHttpServer(handler) ! Bind(interface = serverAddress, port = serverPort)

Then the command will be
Open the port 9001
sbt>re-start --- -Dbuild.env=app1

Open the port 9002
sbt>re-start --- -Dbuild.env=app2

Open the default port 9000
sbt>re-start

3. How to Write Test
come soon…

4. How to Work with Actor
come soon…

5. How to Work with Logback
come soon…

Tips
1. Eclipse is so slow
I try to download and use eclipse from type safe
http://typesafe.com/stack/downloads/scala-ide
And install the JGit for it
http://download.eclipse.org/egit/updates


References:
spray
http://sillycat.iteye.com/blog/1766558
http://sillycat.iteye.com/blog/1766568
http://sillycat.iteye.com/blog/1767203
http://sillycat.iteye.com/blog/1768065

slick
http://sillycat.iteye.com/blog/1767204
http://sillycat.iteye.com/blog/1767865

Source codes
https://github.com/spray/spray
http://spray.io/documentation/spray-testkit/
https://github.com/spray/spray-template

热点排行