[英]How to build an Uber JAR (Fat JAR) using SBT within IntelliJ IDEA?
我正在使用 SBT(在 IntelliJ IDEA 中)构建一个简单的 Scala 项目。
我想知道构建Uber JAR文件(又名 Fat JAR、Super JAR)的最简单方法是什么。
我目前正在使用 SBT,但是当我将 JAR 文件提交到Apache Spark 时,出现以下错误:
线程“main”中的异常 java.lang.SecurityException:Manifest 主要属性的签名文件摘要无效
或者在编译期间出现这个错误:
java.lang.RuntimeException:重复数据删除:在以下内容中发现不同的文件内容:
PATH\\DEPENDENCY.jar:META-INF/DEPENDENCIES
PATH\\DEPENDENCY.jar:META-INF/MANIFEST.MF
看起来是因为我的一些依赖项包括需要在最终 Uber JAR 文件中删除的签名文件 (META-INF)。
我尝试像这样使用sbt-assembly插件:
/project/assembly.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
/project/plugins.sbt
logLevel := Level.Warn
/build.sbt
lazy val commonSettings = Seq(
name := "Spark-Test"
version := "1.0"
scalaVersion := "2.11.4"
)
lazy val app = (project in file("app")).
settings(commonSettings: _*).
settings(
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "1.2.0",
"org.apache.spark" %% "spark-streaming" % "1.2.0",
"org.apache.spark" % "spark-streaming-twitter_2.10" % "1.2.0"
)
)
当我在 IntelliJ IDEA 中单击“ Build Artifact... ”时,我得到一个 JAR 文件。 但我最终遇到了同样的错误......
我是 SBT 的新手,对 IntelliJ IDE 没有太多的尝试。
谢谢。
最后,我完全跳过使用 IntelliJ IDEA 以避免在我的全局理解中产生噪音:)
我开始阅读官方的 SBT 教程。
我使用以下文件结构创建了我的项目:
my-project/project/assembly.sbt
my-project/src/main/scala/myPackage/MyMainObject.scala
my-project/build.sbt
在我的assembly.sbt文件中添加了sbt-assembly插件。 允许我构建一个胖 JAR:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
我的最小build.sbt看起来像:
lazy val root = (project in file(".")).
settings(
name := "my-project",
version := "1.0",
scalaVersion := "2.11.4",
mainClass in Compile := Some("myPackage.MyMainObject")
)
val sparkVersion = "1.2.0"
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % sparkVersion % "provided",
"org.apache.spark" %% "spark-streaming" % sparkVersion % "provided",
"org.apache.spark" %% "spark-streaming-twitter" % sparkVersion
)
// META-INF discarding
mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
{
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case x => MergeStrategy.first
}
}
注意: % "provided"
意味着不在最终的胖 JAR 中包含依赖项(这些库已经包含在我的工作人员中)
注意: META-INF 丢弃受此 answser 启发。
现在我可以通过在我的/my-project根文件夹中运行以下命令来使用 SBT(如何安装它)构建我的胖 JAR:
sbt assembly
我的胖 JAR 现在位于新生成的/target文件夹中:
/my-project/target/scala-2.11/my-project-assembly-1.0.jar
希望能帮助别人。
对于那些想要在 IntelliJ IDE 中嵌入 SBT 的人: 如何从 IntelliJ IDEA 中运行 sbt-assembly 任务?
在 IntelliJ Idea 中构建 Uber JAR/Fat JAR 的 3 步过程:
Uber JAR/Fat JAR :包含所有外部库依赖项的 JAR 文件。
在 IntelliJ Idea 中添加 SBT Assembly 插件
转到ProjectName/project/target/plugins.sbt文件并添加这一行addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
转到ProjectName/build.sbt文件并添加 Uber JAR 打包策略
合并策略:如果关于一个库版本的两个包存在冲突,那么在 Uber JAR 中打包哪个。
丢弃策略:从库中删除一些您不想打包到 Uber JAR 中的文件。
不要添加策略:不要向 Uber JAR 添加一些包。
例如: spark-core
已经存在于你的 Spark 集群中。所以我们不应该把它打包在 Uber JAR 中
合并策略和丢弃策略基本代码:
assemblyMergeStrategy in assembly := { case PathList("META-INF", xs @ _*) => MergeStrategy.discard case x => MergeStrategy.first }
因此,您要求使用此命令MergeStrategy.discard
丢弃 META-INF 文件,而对于其余文件,如果使用此命令MergeStrategy.first
存在任何冲突,则您将首次出现库文件。
不要添加策略基本代码:
libraryDependencies += "org.apache.spark" %% "spark-core" % "1.4.1" %"provided"
如果我们不想将 spark-core 添加到我们的 Uber JAR 文件中,因为它已经在我们的 clutser 上,所以我们在它的库依赖项的末尾添加% "provided"
。
在用于构建包的终端类型sbt assembly
中
将以下行添加到您的项目/plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
将以下内容添加到您的 build.sbt
mainClass in assembly := some("package.MainClass")
assemblyJarName := "desired_jar_name_after_assembly.jar"
val meta = """META.INF(.)*""".r
assemblyMergeStrategy in assembly := {
case PathList("javax", "servlet", xs @ _*) => MergeStrategy.first
case PathList(ps @ _*) if ps.last endsWith ".html" => MergeStrategy.first
case n if n.startsWith("reference.conf") => MergeStrategy.concat
case n if n.endsWith(".conf") => MergeStrategy.concat
case meta(_) => MergeStrategy.discard
case x => MergeStrategy.first
}
Assembly合并策略用于解决创建fat jar时发生的冲突。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.