如何将 Play 2.2 Scala 应用程序创建为 SBT 子项目
Posted
技术标签:
【中文标题】如何将 Play 2.2 Scala 应用程序创建为 SBT 子项目【英文标题】:How to create a Play 2.2 Scala application as an SBT sub-project 【发布时间】:2013-09-28 22:07:43 【问题描述】:我正在尝试创建一个 Scala 应用程序,其中包含一个库项目(我们称之为 common
)、一个 Thrift 服务器项目(我们称之为 server
)和一个 Play Web 应用程序项目(以下称为 web
)。这三个都是用 Scala 编写并用 sbt 构建的。
我的项目结构如下:
myproject/
-common/
...
-server/
...
-web/
-app/
-conf/
...
-project/
-Build.scala
-build.properties
-build.sbt
我的build.sbt
文件(简化了一点)如下所示:
import play.Project._
name := "myproject"
version := "1.0-SNAPSHOT"
lazy val common = project
lazy val web = project
.settings(playScalaSettings: _*)
.dependsOn(common)
lazy val server = project
.dependsOn(common)
lazy val root = project.in(file("."))
.aggregate(common, web, server)
问题在于根项目不是 Play 项目,所以play
命令不起作用(它会出现错误
java.lang.RuntimeException: */*:playRunHooks is undefined.
at scala.sys.package$.error(package.scala:27)
如果我在 SBT 文件中的 version
行之后插入行 playScalaSettings
,我可以通过使根项目看起来像一个 Play 项目来解决这个问题,但是我遇到了另一个问题:play run
命令试图运行根项目,而不是 web
子项目。显然,play run
命令在web
子目录中运行时不起作用,因为那里没有描述项目及其依赖项的 SBT 文件。
我正在寻找一种解决方案,它允许我保留此项目结构(意味着 Play 项目是我的应用程序中的许多子项目之一),同时保留所有 Play 框架的热点,例如代码更改时的热更新(甚至代码在 common
等依赖库中。
我以为我通过运行play
来获取交互式控制台找到了解决方案,然后
project web
run
这可行,但它在命令行上不起作用。 play web/run
出于某种原因运行了根级别的run
命令,如上所述,该命令不起作用,因为根应用程序不是 Play 应用程序。
注意:之前在 Play Framework as SBT Non-Root Module 在 Play 2.0 的上下文中提出了类似的问题,但答案并不令人满意,我也不认为它在 Play 2.2 中仍然正确。
【问题讨论】:
【参考方案1】:如果
play (entering shell)
project web
run
工作,然后你可以从命令行让它工作:
play "project web" "run"
你可以在命令行中做任何你可以在 shell 中做的事情。
我有相同的项目结构,这对我来说效果很好。
顺便说一句,我认为热重载的东西与 Play 无关。它是由 Play 使用的 SBT 提供的增量编译。我认为 play 命令只是一些被黑的 SBT 启动器。
以下命令对我来说很好用:
sbt "project web" "run"
它会通过热重载启动 Play 项目。
我认为你甚至可以使用
sbt "project web" "~run"
每次更改源文件时都会尝试重新编译,而不是等待浏览器刷新,并且会花一些时间。
【讨论】:
【参考方案2】:我认为这是 Play 2.2 中的一个错误,因此我将其报告为 Error "/:playRunHooks is undefined" on running as web/run。 此外,它似乎已在 2.3.x 中修复,因此很可能不会在 2.2 中修复。这是我想出的一个有点书呆子的解决方法:
lazy val root = (project in file(".")).
settings(
playRunHooks := Nil,
playInteractionMode := play.PlayConsoleInteractionMode,
playDefaultPort := 9000,
playMonitoredFiles := (Def.taskDyn
val s = state.value
s.history.current.split("/").headOption match
case Some(ref) =>
Def.task
(playMonitoredFiles in LocalProject(ref)).value
case _ =>
Def.task
playMonitoredFiles.value
).value
)
【讨论】:
以上是关于如何将 Play 2.2 Scala 应用程序创建为 SBT 子项目的主要内容,如果未能解决你的问题,请参考以下文章
如何将 IntelliJ 与 Play Framework 和 Scala 一起使用
如何使用 jre-alpine 基础镜像创建 Scala Play 应用程序的 Docker 镜像