Sbt Assembly重复文件合并问题求助:已尝试方案仍未解决
解决sbt Assembly合并冲突与依赖树显示问题
先别急,咱们一步步拆解你遇到的两个核心问题:依赖树插件无法显示传递依赖,以及即使配置了合并策略仍存在重复内容冲突。
一、先修复依赖树插件不生效的问题
依赖树是排查重复依赖的关键,先确保它能正常工作:
1. 确认插件配置正确
在你的project/plugins.sbt文件中添加对应版本的依赖树插件(注意和你的sbt版本匹配,Scala 2.11.8对应sbt 0.13.x,所以用这个版本):
addSbtPlugin("net.virtual-void" % "sbt-dependency-tree" % "0.10.0-RC1") // 同时确保sbt-assembly插件也正确配置 addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.10")
2. 正确使用依赖树命令
在终端运行以下命令,就能看到完整的依赖关系:
- 查看全量依赖树:
sbt clean dependencyTree - 定位某一个依赖的来源:
sbt whatDependsOn <groupId> <artifactId>
比如想查log4j-core的依赖链:sbt whatDependsOn org.apache.logging.log4j log4j-core
如果还是没输出,检查sbt版本是否和插件兼容——sbt 0.13.x对应插件版本0.10.0-RC1,sbt 1.x则需要用1.2.0及以上版本。
二、解决sbt Assembly重复内容冲突
你已经用了Log4j2MergeStrategy,但冲突仍存在,大概率是合并策略覆盖不全面,或者有未被处理的重复依赖。以下是针对性的优化方案:
1. 完善合并策略配置
在你的build.sbt中,把合并策略调整得更全面,既要覆盖log4j2的特殊文件,也要处理其他常见冲突场景:
import sbtassembly.Log4j2MergeStrategy name := "your-project-name" organization := "your-org" version := "0.1" scalaVersion := "2.11.8" val sparkVersion = "2.1.1" resolvers ++= Seq( "Maven Central" at "https://repo1.maven.org/maven2/", "Spark Packages" at "https://dl.bintray.com/spark-packages/maven/" ) libraryDependencies ++= Seq( "org.apache.spark" %% "spark-core" % sparkVersion % Provided, "org.apache.spark" %% "spark-sql" % sparkVersion % Provided, // 你的其他业务依赖 ) // 核心合并策略配置 assemblyMergeStrategy in assembly := { // 合并META-INF/services下的文件(去重行) case PathList("META-INF", "services", xs @ _*) => MergeStrategy.filterDistinctLines // 丢弃MANIFEST.MF,避免打包时冲突 case PathList("META-INF", "MANIFEST.MF") => MergeStrategy.discard // 保留第一个LICENSE文件,避免重复 case PathList("META-INF", "LICENSE") => MergeStrategy.first // 专门处理log4j2的配置文件和插件 case x if Log4j2MergeStrategy.isLog4j2File(x) => Log4j2MergeStrategy.log4j2MergeStrategy(x) // 处理重复的class文件,优先保留第一个(如果是版本冲突,后续用dependencyOverrides统一) case x if x.endsWith(".class") => MergeStrategy.first // 其他文件沿用默认策略 case x => val defaultStrategy = (assemblyMergeStrategy in assembly).value defaultStrategy(x) } // 强制统一依赖版本,从根源避免传递依赖冲突 dependencyOverrides ++= Seq( "com.google.guava" % "guava" % "14.0.1", // Spark 2.1.1依赖的guava版本 "org.apache.commons" % "commons-lang3" % "3.5" )
2. 精准排查重复冲突
从assembly的报错信息里找到具体的重复文件(比如duplicate entry: org/apache/logging/log4j/core/lookup/JndiLookup.class),然后用依赖树命令找到这些文件来自哪些依赖:
- 如果是同一库的不同版本,用
dependencyOverrides强制统一版本 - 如果是不同库的同名文件,要么排除其中一个依赖(用
exclude),要么给该文件单独设置合并策略
三、额外注意事项
- Spark依赖建议加
% Provided,避免打包时把Spark自带的库也打进去,减少冲突概率 - 如果使用了其他日志框架(比如logback),记得排除和log4j2冲突的依赖,比如在Spark依赖里加
exclude("org.slf4j", "slf4j-log4j12")
内容的提问来源于stack exchange,提问作者donald
相关产品推荐
相关产品推荐

