如何在IntelliJ IDEA中使用SBT构buildUber JAR(Fat JAR)?
我正在使用SBT(在IntelliJ IDEA中)构build一个简单的Scala项目。
我想知道什么是最简单的方法来build立一个Uber JAR文件(又名脂肪JAR,超级JAR)。
我目前正在使用SBT,但是当我将我的JAR文件提交给Apache Spark时 ,出现以下错误:
线程“main”中的exceptionjava.lang.SecurityException:Manifest主要属性的签名文件摘要无效
或编译期间出现这个错误:
java.lang.RuntimeException:重复数据删除:在以下文件中find不同的文件内容:
PATH \ DEPENDENCY.jar:META-INF / DEPENDENCIES
PATH \ DEPENDENCY.jar:META-INF / MANIFEST.MF
它看起来像是因为我的一些依赖关系包括签名文件(META-INF),它需要在最终的Uber JAR文件中被删除。
我试图用这样的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教程 。
我使用以下文件结构创build了我的项目:
my-project/project/assembly.sbt my-project/src/main/scala/myPackage/MyMainObject.scala my-project/build.sbt
在我的assembly.sbt文件中添加了sbt-assembly 插件 。 让我build立一个胖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") ) libraryDependencies ++= Seq( "org.apache.spark" %% "spark-core" % "1.2.0" % "provided", "org.apache.spark" %% "spark-streaming" % "1.2.0" % "provided", "org.apache.spark" % "spark-streaming-twitter_2.10" % "1.2.0" ) // 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丢弃。
注意 : %
和%%
含义
现在,我可以通过在my / my-project根文件夹中运行以下命令来使用SBT( 如何安装它 )来构build我的胖JAR:
sbt assembly
我的胖JAR现在位于新生成的/目标文件夹中:
/my-project/target/scala-2.11/my-project-assembly-1.0.jar
希望能帮助别人。
对于那些想要在IntelliJ IDE中embeddedSBT的人: 如何从IntelliJ IDEA中运行sbt-assembly任务?
IntelliJ构buildUber JAR / Fat JAR的3个步骤过程:
Uber JAR / Fat JAR :具有所有外部库pipe理器依赖关系的JAR文件。
-
在IntelliJ Idea中添加SBT Assembly插件
转到ProjectName / project / target / plugins.sbt文件并添加此行
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
-
在build.sbt中添加合并,放弃和不添加策略
转到ProjectName / build.sbt文件并添加用于打包Uber JAR的策略
合并策略:如果在两个软件包中存在关于一个版本的库的冲突,那么在Uber JAR中打包哪一个。
丢弃策略:从库中删除一些你不想在Uber JAR中打包的文件。
不要添加策略:不要添加一些包到Uber JAR。
例如:spark-core
已经存在于你的Spark Cluster中,所以我们不应该把它包装在Uber JAR中合并策略和放弃策略基本代码:
assemblyMergeStrategy in assembly := { case PathList("META-INF", xs @ _*) => MergeStrategy.discard case x => MergeStrategy.first }
因此,如果使用此命令
MergeStrategy.discard
,如果存在任何冲突,则您要求使用此命令MergeStrategy.discard
放弃META-INF文件,并请求放弃第一次出现库文件的其余文件。不要添加策略基本代码:
libraryDependencies += "org.apache.spark" %% "spark-core" % "1.4.1" %"provided"
如果我们不想将spark-core添加到我们的Uber JAR文件中,因为它已经在我们的configuration文件中了,所以我们在它的库依赖项的末尾添加
% "provided"
。 -
构buildUber JAR及其所有的依赖关系
在terminaltypes的
sbt assembly
用于构build包
瞧! Uber JAR被build立。 JAR将在ProjectName / target / scala-XX中
将以下行添加到您的project / 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合并策略用于解决创build胖jar时发生的冲突。