Статьи

Создание отдых API с помощью спрея

Построить api отдыха с помощью akka и спрея легко. Вот как я это сделал:
SprayApiApp:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
import akka.actor.{ActorSystem, Props}
import akka.io.IO
import akka.pattern.ask
import akka.util.Timeout
import spray.can.Http
import scala.concurrent.duration._
 
object SprayApiApp extends App {
  //we need an ActorSystem to host our application in
  implicit val system = ActorSystem("SprayApiApp")
 
  //create apiActor
  val apiActor = system.actorOf(Props[ApiActor], "apiActor")
 
  //timeout needs to be set as an implicit val for the ask method (?)
  implicit val timeout = Timeout(5.seconds)
 
  //start a new HTTP server on port 8080 with apiActor as the handler
  IO(Http) ? Http.Bind(apiActor, interface = "localhost", port = 8080)
}

ApiActor:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import akka.actor.{ActorLogging, Actor}
import spray.http.MediaTypes
import spray.httpx.SprayJsonSupport._
import spray.json.DefaultJsonProtocol
import spray.routing._
 
object RobotProtocol extends DefaultJsonProtocol {
  //Our domain class
  case class Robot(name: String)
 
  //We use the default json marshalling for Robot.
  //There are multiple jsonFormat methods in DefaultJsonProtocol. Depending on how many parameters the model class has.
  //Robot has just one, so we use jsonFormat1
  implicit val RobotFormat = jsonFormat1(Robot)
}
import RobotProtocol._
 
class ApiActor extends Actor with HttpService with ActorLogging {
  //A list of our domain objects
  var robots = List(Robot("R2D2"), Robot("Asimo"))
 
  //The HttpService trait defines only one abstract member, which
  //connects the services environment to the enclosing actor or test
  def actorRefFactory = context
 
  //This actor only runs our route, but you could add
  //other things here, like request stream processing or timeout handling
  def receive = runRoute(apiRoute)
 
  //Notice that both path methods return a Route. We need to chain them together with ~
  val apiRoute: Route =
    path("robots") {
      get { //with get we will return our current list of robots
        log.info("Building get route")
        complete {
          log.info("Executing get route")
          //complete will return the result in an appropriate format
          //With SprayJsonSupport it knows how to marshall a List to json
          //With RobotFormat it knows how to marshall Robot
          robots
        }
      } ~ post { //With post we will add a robot
        log.info("Building post route")
        handleWith { robot: Robot =>  //handleWith will unmarshall the input
          log.info("Executing post route")
          robots = robot :: robots
          robot //handleWith will also marshall the result. Here we simply return the new robot.
        }
      }
    } ~ path("") { //When we go to localhost:8080/ just show a link to localhost:8080/robots
      respondWithMediaType(MediaTypes.`text/html`) { //XML is marshalled to `text/xml` by default, so we simply override here
        complete {
          <a href="/robots">The list of robots</a>
        }
      }
    }
}

Когда мы запустим это, мы сможем получить http: // localhost: 8080 / robots и получить список роботов:

1
2
3
4
5
[{
  "name": "R2D2"
}, {
  "name": "Asimo"
}]

И мы можем сделать сообщение на http: // localhost: 8080 / robots, чтобы добавить робота: с заголовком Content-Type: application/json

1
2
3
{
  "name": "Optimus Prime"
}

Когда мы посмотрим на протоколирование, мы заметим, что код в построении маршрута будет запускаться только один раз при запуске.

Только код внутри complete и handleWith будет выполняться с каждым запросом.

1
2
3
4
5
[INFO] [03/15/2015 12:08:21.572] [SprayApiApp-akka.actor.default-dispatcher-3] [akka://SprayApiApp/user/apiActor] Building get route
[INFO] [03/15/2015 12:08:21.578] [SprayApiApp-akka.actor.default-dispatcher-3] [akka://SprayApiApp/user/apiActor] Building post route
[INFO] [03/15/2015 12:08:22.144] [SprayApiApp-akka.actor.default-dispatcher-4] [akka://SprayApiApp/user/IO-HTTP/listener-0] Bound to localhost/127.0.0.1:8080
[INFO] [03/15/2015 12:08:27.243] [SprayApiApp-akka.actor.default-dispatcher-3] [akka://SprayApiApp/user/apiActor] Executing get route
[INFO] [03/15/2015 12:08:30.066] [SprayApiApp-akka.actor.default-dispatcher-4] [akka://SprayApiApp/user/apiActor] Executing post route

с благодарностью: http://blog.michaelhamrah.com/2013/06/scala-web-apis-up-and-running-with-spray-and-akka/

Ссылка: Создание API для отдыха с помощью спрея от нашего партнера JCG Таммо Сминии в блоге JDriven .