Akka HTTP路由和封送

时间:2016-03-30 20:46:59

标签: json scala akka-http

我刚刚开始使用Akka HTTP,我在路由DSL和编组方面遇到了一些麻烦。 'route'设置中的波浪号导致错误:

  

value~不是akka.http.scaladsl.server.RequestContext⇒的成员   scala.concurrent.Future [akka.http.scaladsl.server.RouteResult]   可能的原因:在'value〜'之前可能缺少分号?

此外,'get'子句中的JSON编组导致错误:

  

◾无法找到JsonWriter或JsonFormat类型   scala.collection.immutable.Map [String,scala.collection.mutable.Map [String,Tweet]]

     

对方法toJson没有足够的参数:(隐式编写者:   spray.json.JsonWriter [scala.collection.immutable.Map [字符串,scala.collection> .mutable.Map [字符串,鸣叫]]])spray.json.JsValue。   未指定的值参数编写器。

我非常仔细地遵循了文档示例,因此我非常感谢帮助您理解这些错误以及如何解决这些错误。谢谢。

API

import akka.actor.ActorSystem
import scala.concurrent.Future
import akka.stream.ActorMaterializer
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives.path
import akka.http.scaladsl.server.Directives.pathPrefix
import akka.http.scaladsl.server.Directives.post
import akka.http.scaladsl.server.Directives.get
import akka.http.scaladsl.server.Directives.complete
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.server.Directives.{entity, as}
import akka.http.scaladsl.model.StatusCodes.{Created, OK}
import spray.json._
import DefaultJsonProtocol._
import akka.stream.Materializer
import scala.concurrent.ExecutionContext

trait RestApi {
  import TweetProtocol._
  import TweetDb._

  implicit val system: ActorSystem
  implicit val materializer: Materializer
  implicit val execCtx: ExecutionContext

  val route =
    pathPrefix("tweets") {
      (post & entity(as[Tweet])) { tweet =>
        complete {
          Created -> Map("id" -> TweetDb.save(tweet)).toJson
        }
      } ~ 
      (get) {
        complete {
          OK -> Map("tweets" -> TweetDb.find()).toJson
        }
      } 
    }   
}

object TweetApi extends App with RestApi {
  implicit val system = ActorSystem("webapi")
  implicit val materializer = ActorMaterializer()
  implicit val execCtx = system.dispatcher

  val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)

  println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
  Console.readLine()

  bindingFuture.flatMap(_.unbind()).onComplete { _ => system.shutdown() }
}

协定

import spray.json.DefaultJsonProtocol

case class Tweet(author: String, body: String)

object TweetProtocol extends DefaultJsonProtocol {
  implicit val TweetFormat = jsonFormat2(Tweet.apply)
}

伪数据库

import scala.collection.mutable.Map

object TweetDb {
  private var tweets = Map[String, Tweet]()

  def save(tweet: Tweet) = {
    val id: String = java.util.UUID.randomUUID().toString()
    tweets += (id -> tweet)
    id
  }

  def find() = tweets

  def findById(id: String) = tweets.get(id)
}

1 个答案:

答案 0 :(得分:4)

对于您的第一个错误,请尝试评论中的建议,即。从指令中导入全部

第二部分

  

◾无法为scala.collection.immutable.Map找到JsonWriter或JsonFormat类型类[String,scala.collection.mutable.Map [String,Tweet]]

     

method方法toJson的参数不够:(隐式编写器:spray.json.JsonWriter [scala.collection.immutable.Map [String,scala.collection> .mutable.Map [String,Tweet]]])spray.json .JsValue。未指定的值参数编写器。

您需要为Map[String, mutable.Map[String, Tweet]]

定义JsonFormat

通过在TweetProtocol中创建一个对象,扩展RootJsonFormat 例如

type DBEntry = Map[String, mutable.Map[String, Tweet]]
object TweetProtocol extends DefaultJsonProtocol {
  implicit object DBEntryJsonFormat extends RootJsonFormat[DBEntry] {
    override def read(json: JSValue) { 
      // your implementation
    }
    override def write(dbEntry: DBEntry) {
      // implementation
    }
  }
}