我正在尝试为个人资料管理提供休息服务.所以我有以下uri的配置文件:
host/profile/id123123/:action
Run Code Online (Sandbox Code Playgroud)
但是对于具有不同仪表板的不同用户,存在不同的配置文件类型,因此我想提取profileType并id作为顶部路径并在此下使用不同的操作.我试着用DRY方式写它:
path(Segment / "id" ~ Segment) { (profileType, id) ?
get {
profileType match {
case "admin" ? loadProfilePage[Admin](id)
}
} ~
path("update") {
complete("Profile updated")
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我在地址栏中键入以下内容:
localhost/admin/id123123/update
Run Code Online (Sandbox Code Playgroud)
它抛出服务器异常.有什么问题?
我正在学习Spray和Akka.使用其中一个路由存根构建了一个简单的Spray路由应用程序 -
path("blog" / LongNumber) {
blogId =>
respondWithMediaType(MediaTypes.`application/json`) {
get {
request => BlogFetchActor ! Get(blogId)
}
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,我在我的喷涂路由定义(在实现HttpService的类中)中将消息分派给请求中具有ID(blogId)的另一个Actor.BlogFetchActor应该从数据库中获取数据并响应发送者.我的编码如下 -
def receive: Receive = LoggingReceive {
case Get(id: Long) => {
log.debug("Retrieving blog with id %d".format(id))
sender ! ReturnBlog(get(id))
}
}
Run Code Online (Sandbox Code Playgroud)
来自路线的Actor消息正在进入我的BlogFetchActor.我的BlogFetchActor也完成了从数据库中获取数据的工作.但是当我尝试将响应发送回发件人HttpService,ReturnBlog消息时,它不起作用.消息最终在DeadLetters中,我在我的日志中看到以下内容 -
从演员[akka:// on-spray-can/user/blog-service/blog#1301907662]到演员[akka:// on-spray-can/deadLetters]的消息[in.bharathwrites.BlogFetchActor $ ReturnBlog]不是交付.
为什么回复给发件人的回复不起作用?我究竟做错了什么?我怎么能做到这一点?我试过阅读Spray文档和ScalaDoc,但无法弄清楚问题.我不够精通阅读Spray代码并了解原因......提前致谢
我正在尝试设置一个基本的Spray Can服务器.在代码中,我看到了这个:
IO(Http) ! Http.Bind(service, interface = "localhost", port = 8080)
Run Code Online (Sandbox Code Playgroud)
我想从application.conf文件配置该端口(8080).但是,conf文件的格式(http://spray.io/documentation/1.2-M8/spray-can/configuration/)没有定义端口.
这是否意味着实现此目的的方法是自己定义端口配置,并从application.conf中读取它?如果是这样,这是怎么做到的?
我正在使用Spray进行一些Http请求处理.对于一个请求,我启动一个actor并将有效负载发送给actor以进行处理,并且在演员完成有效负载之后,我呼吁context.stop(self)演员将演员缠绕下来.这个想法是为了防止演员身上的过度饱和.机.
这就是我设置的方式..
在httphandler.scala,我的路线设置如下:
path("users"){
get{
requestContext => {
val userWorker = actorRefFactory.actorOf(Props(new UserWorker(userservice,requestContext)))
userWorker ! getusers //get user is a case object
}
}
} ~ path("users"){
post{
entity(as[UserInfo]){
requestContext => {
userInfo => {
val userWorker = actorRefFactory.actorOf(Props(new UserWorker(userservice,requestContext)))
userWorker ! userInfo
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的UserWorker演员定义如下:
trait RouteServiceActor extends Actor{
implicit val system = context.system
import system.dispatcher
def processRequest[responseModel:ToResponseMarshaller](requestContex:RequestContext)(processFunc: => responseModel):Unit = {
Future{
processFunc
} onComplete {
case Success(result) => …Run Code Online (Sandbox Code Playgroud) 我想采用一个返回a的函数,并将其Future[Option[String]]与spray routing的onComplete指令结合使用.但无论我做什么,我似乎无法让它发挥作用.
假设我有以下功能:
def expensiveOperation: Future[Option[String]] = { ... do stuff ... }
Run Code Online (Sandbox Code Playgroud)
然后我想定义我的一部分Route:
onComplete(expensiveOperation) {
case Success(string) => complete(string)
case Failure(_) => complete("failure")
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在不编写单独的函数的情况下将其Future[Option[String]]转换为基本函数Future[String]?
此代码导致编译错误could not find implicit value for parameter marshaller:
spray.httpx.marshalling.ToResponseMarshaller[List[akka.actor.ActorRef]].
我不认为问题是ActorRef,因为改变它.mapTo[List[String]]显示相同的编译错误
一般来说,喷雾如何编组与所有暗示有点混淆 - 有没有办法使这个明确,例如ListProtocol.marshal(value)?
import akka.actor.Actor
import spray.http.HttpResponse
import spray.http.HttpRequest
import spray.http.Uri
import spray.http._
import spray.routing._
import HttpMethods._
import akka.actor.ActorRef
import akka.pattern.ask
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.Success
import scala.util.Failure
import spray.http.StatusCodes.InternalServerError
import spray.json.DefaultJsonProtocol
import spray.httpx.SprayJsonSupport._
import spray.httpx.marshalling._
import spray.http._
class HttpApi(val manager: ActorRef) extends HttpServiceActor {
def receive = runRoute {
path("nodes") {
get {
onComplete(manager.ask(NodeList())(3.seconds).mapTo[List[ActorRef]]) {
case Success(value) => {
// …Run Code Online (Sandbox Code Playgroud) 看看喷雾API,它RequestContext是不可变的并RequestContext.reject返回Unit- 那么Spray路由如何知道"请求"被拒绝了?
http://spray.io/documentation/1.2.2/spray-routing/key-concepts/routes/
即:我们说我们有路线:a-> b
如果b拒绝请求(通过调用RequestContext.reject)如何a通知它?
我想我不确定"响应者"(参见文档中的响应者链)的文档意味着什么RequestContext.响应者b会是a吗?或者响应者是Actor发起http请求的原始人吗?
如何解析json与喷json使用蛇案(下划线表示法)而不是骆驼案?
例如
case class Test(subjectDescription: String)
"{\"subject_description\":\"Medicine\"}".parseJson.convertTo[Test]
Run Code Online (Sandbox Code Playgroud)
应该工作,而不是抛出异常.
我一直在努力学习在 docker 中运行一个 sbt 项目。我也想用喷雾。我正在遵循 sbt-docker 在 github 中提供的示例: https://github.com/marcuslonnberg/sbt-docker/tree/master/examples/package-spray 当我拉项目时,它工作正常,我可以运行docker 容器也是如此。
project > project > PackageSprayBuild.scala 中有一个文件我不知道这个文件是如何使用的。此外,给定的示例没有 plugins.sbt 文件。
然后我尝试创建我的单独项目。
我的plugins.sbt看起来像这样:
logLevel := Level.Warn
addSbtPlugin("se.marcuslonnberg" % "sbt-docker" % "1.2.0")
Run Code Online (Sandbox Code Playgroud)
我的build.sbt看起来与我上面提到的示例几乎相同。
name := "demo-docker-sbt"
version := "1.0"
scalaVersion := "2.11.7"
resolvers += "spray repo" at "http://repo.spray.io/"
libraryDependencies ++= Seq(
"io.spray" % "spray-can" % "1.2.0",
"io.spray" % "spray-routing" % "1.2.0",
"com.typesafe.akka" %% "akka-actor" % "2.2.3")
enablePlugins(DockerPlugin)
// Make docker depend on the package task, which generates a …Run Code Online (Sandbox Code Playgroud) 我正在学习使用构建服务器Akka-Http,这是我到目前为止所写的
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.stream.{Materializer, ActorMaterializer}
import spray.json.DefaultJsonProtocol
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import scala.concurrent.ExecutionContextExecutor
// todo() : add event timestamp
case class ECFailure(symbolicName:String)
trait Protocols extends DefaultJsonProtocol {
implicit val ecFailureFormat = jsonFormat1(ECFailure.apply)
}
trait EmailService extends Protocols {
implicit val system: ActorSystem
implicit def executor: ExecutionContextExecutor
implicit val materializer: Materializer
val route =
logRequestResult("email-service") {
pathPrefix("ec") {
(post & entity(as[ECFailure])) { ecFailure =>
complete {
println("received: " + ecFailure)
"Done"
}
}
}
path("") { …Run Code Online (Sandbox Code Playgroud) 所以我有一堆采用这种格式的案例类:
case class A(value: String)
case class B(value: String)
case class C(value: String)
Run Code Online (Sandbox Code Playgroud)
我在函数中接受了几个Option [String]值作为参数,如果参数中的值不是None,我想创建Option [A],Option [B].
我现在这样做:
val first = parameterOptional match {
case Some(theStringValue) => Some(A))
case None => None
}
Run Code Online (Sandbox Code Playgroud)
它有效,但我想知道是否有更简洁的方法来做到这一点,我对Scala很新.
示例中的变量名称显然已被更改.
谢谢
UserGetResponse和GeneralResponse是BaseResponse的子类,如下所示:
abstract class BaseResponse()
Run Code Online (Sandbox Code Playgroud)
我用来检索用户的函数如下:
def userGet(userId: Int)(implicit ec: ExecutionContext): Future[BaseResponse] = Future {
val response = users.get(userId) map { user =>
val userRes = new UserResponse(user.id, user.firstname, user.lastname, user.organisationid, user.email, user.password, user.usertype)
new UserGetResponse(1, "Successful retrieved the user.", userRes)
} getOrElse {
GeneralResponse(0, s"Error retrieving user. User does not exist.")
}
}
Run Code Online (Sandbox Code Playgroud)
其中users是另一个定义了get,insert等方法的类.我收到以下编译错误:
type mismatch;
[error] found : Unit
[error] required: package.name.BaseResponse
[error] }
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
我正在尝试使用Spray将以下案例类与JSON相互转换:
case class Interval(lower: Int, upper: Int)
Run Code Online (Sandbox Code Playgroud)
这可以通过以下方式实现:
implicit val intervalFormat = jsonFormat2(Interval)
Run Code Online (Sandbox Code Playgroud)
这样可以编译,但是会给出运行时错误:
无法自动确定案例类字段名称和“间隔”的顺序,请使用“ jsonFormat”重载并使用明确的字段名称规范
搜索此错误表明,通常在子类声明其他字段时会出现此错误,此处不是这种情况。
我是否误以为Spray应该能够自动格式化间隔类?
如果是这样,那么(如错误消息所示)我是否应该为格式化程序提供有关Interval字段的更明确的信息?如何最容易实现?
编辑:@retrospectacus的答案提供了一些有用的观点,但是它们都不能解决问题。我采用的解决方法是对字段的类型和名称进行明确描述:
implicit val intervalFormat = jsonFormat[Int, Int,Interval](Interval, "lower", "upper")
Run Code Online (Sandbox Code Playgroud)
这行得通,但我仍然悬而未决,因为尚不清楚为什么有必要这样做。
scala ×13
spray ×13
akka ×5
json ×2
spray-json ×2
actor ×1
akka-http ×1
apache-spark ×1
asynchronous ×1
docker ×1
port ×1
rest ×1
routing ×1
sbt ×1
spray-dsl ×1