如何在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文件。

  1. 在IntelliJ Idea中添加SBT Assembly插件

    插件sbt路径

    转到ProjectName / project / target / plugins.sbt文件并添加此行addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")

  2. 在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"

  3. 构buildUber JAR及其所有的依赖关系

    sbtassembly

    在terminaltypes的sbt assembly用于构build包

瞧! Uber JAR被build立。 JAR将在ProjectName / target / scala-XX中

JarBuilt

将以下行添加到您的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时发生的冲突。