【问题标题】:Where place compiled Javascript class files for SBT and Play Framework 2.1 to find them?为 SBT 和 Play Framework 2.1 编译的 Javascript 类文件在哪里找到它们?
【发布时间】:2012-11-29 21:51:11
【问题描述】:

我应该把我编译(通过 Rhino)的 Javascript 类放在哪里,以便它们 在编译期间包含在类路径中,并包含在生成的 dist捆绑?

Play Framework 2.1-RC1 + SBT 会忽略它们,有时在 编译,有时在生成 dist 包时。

1。将生成的文件放在classes/classes_managed/

如果我将生成的 .class 文件放在此处或此处:
target/scala-2.10/classes/ target/scala-2.10/classes_managed/

然后compilerun 工作正常。但是stagedist 期间的一些奇怪的编译步骤(什么?!)失败了:它不会找到编译的类。

2。将类放在专用目录中

如果我将生成的 .class 文件放在这里: target/scala-2.10/compiledjs-classes/

并在 SBT 的配置中添加一个类路径条目:

object ApplicationBuild extends Build {
  ...
  def mainSettings = List(
    ...,
    unmanagedClasspath in Compile <+= (baseDirectory) map { bd =>
      Attributed.blank(bd / "target/scala-2.10/compiledjs-classes")
    },
    ...)

然后compilerunstagedist 工作正常。然而!当我解压缩并 启动生成的 .zip 文件(通过dist 生成),然后启动应用程序 在运行时失败,因为编译的 Javascript 类不包含在 .zip。

3。将类放在 lib/ 文件夹中

然后compile 将找不到类文件。 (我放置了例如compiledjs.HtmlSanitizerJslib/compiledjs/HtmlSanitizerJs.class.)


我该怎么办?我的意思是,什么是有效的,什么是最佳做法?

无论如何,现在我将生成的类复制到
target/scala-2.10/compiledjs-classes/(因此编译工作)和
target/scala-2.10/classes/(因此它们包含在生成的 .zip 中)
这行得通,但感觉很不对。

(( 奇怪的是,在旧版本的 Play Framework 上一切正常 (早于 RC-1)当我使用 PlayProject 而不是 play.Project 时。 然后我只将生成的类保存在target/scala-2.10/classes/ 中。 ))

【问题讨论】:

  • 您可以尝试 2. 使用不在目标中但在 baseDirectory 中的文件夹吗?
  • @Schleichardt 完成。编译有效,但stagedist 不起作用(因为java.lang.NoClassDefFoundError,当找不到生成的类时)。
  • 而且,在 SBT 中,classpath 命令不会列出 the-folder-that-is-not-in-target-but-in-the-baseDirectory ,即在我的情况下compiledjs-classes。但是,show full-classpath 确实 列出了该文件夹 compiledjs-classes。所以我所做的似乎是告诉 SBT 仅在编译时包含该文件夹,而不是在生成 dist 时包含该文件夹?
  • 在 SBT 中,clean 不会删除 compiledjs-classes 文件夹。
  • 对于清洁问题,有一个解决方案:stackoverflow.com/questions/10471596/…

标签: playframework sbt rhino playframework-2.1


【解决方案1】:

我找不到将类文件放入舞台任务的 jar 的方法。作为一种解决方法,我在舞台上生成一个 JAR 文件,并在运行时将类路径设置为基本文件夹中的“rhino”文件夹。

我为您创建了一个要点,因此您可以查看并尝试:https://gist.github.com/4321216rhino/so/Example.class 表示一个 Rhino 类,但它只是一个返回字符串的 Java 类。

在你的 Build.scala 中添加:

  val rhinoJarName = "rhino.jar"
  val folderForRhinoJar = unmanagedBase
  val rhinoClasspath = (baseDirectory) map { base => Attributed.blank(base / "rhino")}
  val rhinoClassesToJar = TaskKey[Unit]("rhino-classes-to-jar")
  val rhinoClassesToJarInitializer = (base: File, folderForJar: File) => {
    val rhinoFolder = new File(base, "rhino")
    val isClassFile = (file: File) => file.getName.endsWith("class")
    val classFiles =  rhinoFolder.***.filter(isClassFile).get
    val sources = classFiles map { file =>
      file -> file.getCanonicalPath.drop(rhinoFolder.getCanonicalPath.length + 1)
    }
    IO.jar(sources, folderForJar / rhinoJarName, new java.util.jar.Manifest())
  }

  val main = play.Project(appName, appVersion, appDependencies).settings(
    unmanagedClasspath in Compile <+= rhinoClasspath,
    unmanagedClasspath in Runtime <+= rhinoClasspath,
    rhinoClassesToJar <<= (baseDirectory, folderForRhinoJar) map rhinoClassesToJarInitializer,
    playStage <<= playStage.dependsOn(rhinoClassesToJar),
    playStage <<= (playStage, folderForRhinoJar) map {(unused, folder) =>
      IO.delete(folder / rhinoJarName)
    },
    cleanFiles <+= folderForRhinoJar { _ / rhinoJarName } //make sure jar will be deleted if play stage does not finish and cleanup jar
  )

【讨论】:

  • 感谢这个详细的示例 :-) 我不确定将类放在 JAR 中并将 JAR 包含在构建中是否比将类直接复制到目标是否“更好” /scala-2.10/classes/ 文件夹?我认为在我的情况下,后一种方法实际上更简单一些,因为我正在调用 Makefile 脚本,并且我只是添加了一个 cp … 行。
  • 我不明白的一个例子是:在运行 stage/dist 时,Play 如何知道包含生成的 JAR? rhinoClassesToJar 创建 JAR,因为 playStage.dependsOn(rhinoClassesToJar) — 但是然后呢? JAR 被创建,但不是必须告诉 SBT 以某种方式将其包含在生成的文件包中吗?
  • SBT 有时难以阅读。真正发生了什么:我覆盖了play dist。首先在 lib 文件夹 (unmanagedBase) 中创建一个带有 rhino 类的 JAR,然后运行真正的 dist 命令并查看 rhino.jar 并包含它,然后删除 JAR。
猜你喜欢
  • 1970-01-01
  • 2016-05-14
  • 1970-01-01
  • 2013-05-13
  • 2017-02-11
  • 2016-01-17
  • 2013-02-04
  • 1970-01-01
  • 2012-11-26
相关资源
最近更新 更多