gpt4 book ai didi

scala - 如何隐藏不可执行的 Scala 库的依赖项?

转载 作者:行者123 更新时间:2023-12-01 10:12:06 25 4
gpt4 key购买 nike

花了几个小时试图找出如何做到这一点。在此过程中,我研究了一些看似有希望的问题,但似乎没有一个与我正在做的事情很相符。

我有三个库 jar,我们称它们为 MSH。图书馆 M 有这样的东西:

case class MyModel(x: Int, s: String) 

然后库 S 使用 play-json 库 2.3.8 版为 M

定义的类提供隐式序列化程序
trait MyModelSerializer {
implicit val myModelFormt = Json.format[MyModel]
}

然后将它们捆绑在一起成为一个方便的对象以供导入

package object implicits extends MyModelSerializer extends FooSerizlier // etc

这样,在库 H 中,当它对各种服务执行 HTTP 调用时,它只是从 S 导入 implicits 然后我调用 Json.validate[MyModel] 从我的网络服务中取回我需要的模型。这一切都很好,但我正在开发一个运行 play 2.4 的应用程序,当我将 H 包含到项目中并尝试使用它时,我遇到了:

java.lang.NoSuchMethodError: play.api.data.validation.ValidationError.<init>(Ljava/lang/String;Lscala/collection/Seq;)

我认为这是由使用 play-json 版本 2.4.6 的 play 2.4 引起的。不幸的是,这些只是一个次要版本,这意味着尝试只使用旧库,如:

// In build.sbt
"com.typesafe.play" %% "play-json" % "2.3.8" force()

导致应用程序中的所有代码都无法编译,因为我正在使用 JsError.toJson 之类的东西,它们不是 play-json 2.3.8 的一部分。我可以更改尝试使用该方法的 14 个左右的位置,但考虑到异常,我觉得即使我这样做也无济于事。

关于这一点,我记得在我使用 maven 的日子里,我可以在构建过程中屏蔽依赖项。所以我开始考虑,如果我可以在 H 中隐藏 play-json 2.3.8 依赖项,那将解决问题。由于问题似乎是在 H 中调用 Json.* 正在使用来自 play-json 2.4.6 的 Json 对象。

不幸的是,我在网上能找到的唯一表明具有遮蔽能力的东西是 sbt-assembly。我找到了一个 great answer关于如何为一个 fat jar 子做到这一点。但我不认为我可以使用 sbt-assembly 因为 H 不是可执行的,它只是一个库 jar。我通读了 question like my own但答案是指 sbt-assembly 所以它对我没有帮助。

Another question seems somewhat promising但我真的无法理解我将如何使用它/我将把代码本身放在哪里。我还查看了 sbt manual ,但没有什么是我需要的。

我不能只更改 S 以使用 play-json 2.4.6,因为我们也在 play 2.3 应用程序中使用 H因此它需要能够在两者中使用。

如果我无法完成某种着色,现在我唯一能想到的就是让 H 不使用 S 而是要求隐含某种序列化器/反序列化器,然后连接适当的 json (dee) 序列化器。所以在这里我问的是如何使用不是可执行 jar 的东西正确地使用 sbt,因为我只想在绝对必要的情况下重写。如果我遗漏了什么(比如 sbt-assembly 也能够隐藏不可执行的 jar),如果你能指出我一定遗漏的文档,我会把它作为答案。

最佳答案

Yuval Itzchakov 所示, sbt-assembly 不必构建可执行 jar,也可以隐藏库代码。此外,除了需要被遮蔽的那些之外,没有传递依赖的打包也可以完成,这将保持打包的 jar 的大小并让其余的依赖照常通过。

手动寻找传递依赖是我最终不得不做的,但如果有人有办法自动做到这一点,那将是对这个答案的一个很好的补充。无论如何,这就是我需要对 H 库的构建文件执行的操作,以使其正确着色 play-json 库。

  1. 在 sbt 控制台上找出正在使用的依赖项 show compile:dependencyClasspath
  2. 捕获任何与 play 相关的东西(因为我只使用 play-json 而没有其他我可以假设 play = 需要着色)
  3. 同时遮蔽 S 模型,因为它们也依赖于 play-json,因此为了避免传递依赖性带来非遮蔽播放 2.3.8,我必须遮蔽我的序列化程序。
  4. 将 sbt-assembly 添加到项目中,然后更新 build.sbt 文件

构建.sbt

//Shade rules for all things play:
assemblyShadeRules in assembly := Seq(
ShadeRule.rename("play.api.**" -> "shade.play.api.@1").inAll
)

//Grabbed from the "publishing" section of the sbt-assembly readme, excluding the "assembly" classifier
addArtifact(artifact in (Compile, assembly), assembly)

// Only the play stuff and the "S" serializers need to be shaded since they use/introduce play:
assemblyExcludedJars in assembly := {
val cp = (fullClasspath in assembly).value
val toIncludeInPackage = Seq(
"play-json_2.11-2.3.8.jar",
"play-datacommons_2.11-2.3.8.jar",
"play-iteratees_2.11-2.3.8.jar",
"play-functional_2.11-2.3.8.jar",
"S_2.11-0.0.0.jar"
)
cp filter {c => !toIncludeInPackage.contains(c.data.getName)}
}

然后我不再尝试运行它时遇到任何异常。我希望这可以帮助其他有类似问题的人,如果有人有办法自动获取依赖项并按它们进行过滤,我会很乐意用它更新答案。

关于scala - 如何隐藏不可执行的 Scala 库的依赖项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40184872/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com