wor*_*138 20 java intellij-idea pom.xml maven maven-dependency
我正在努力解决如何处理jar依赖地狱的问题.我有一个使用一些aws sdk的Maven-IntelliJ Scala项目.最近添加kinesis sdk引入了不兼容的Jackson版本.
我的问题是:我如何系统地解决Jar地狱的问题?
我理解类加载器以及maven如何在重复的Jars之间选择,但我仍然对解决问题的实际步骤感到茫然.
我此刻的尝试是基于反复试验,我在杰克逊的例子中概述了这里:
mvn dependency:tree用来确定我实际使用的Jackson版本(问题2:是否有一种自动方式询问maven正在使用哪个版本的jar,而不是梳理树输出?).mvn dependency:tree在添加Kinesis SDK之前和之后比较 输出,以检测mvn dependency:tree输出中的差异 ,并希望看看Jackson版本是否发生了变化.(问题3:当发生依赖性解析时,maven如何使用着色jar中的库?与其他任何一个相同?).最后,在比较树输出之后,我尝试在POM中明确添加最新的Jackson工作版本,以触发maven依赖解析链中的优先级.如果最新版本不起作用,我会添加下一个最新的lib,依此类推.
整个过程非常繁琐.除了我提出的具体问题外,我也很好奇其他人对这个问题的系统性方法.有没有人有他们使用的资源?
A_D*_*teo 19
然后,我查看Jackson文档,了解添加或删除方法的时间.这通常非常繁琐,因为我手动检查每个版本的api文档(问题1:有更好的方法吗?)
为了检查API(破坏)兼容性,有几种工具可以自动分析罐子并为您提供正确的信息.从这个 Stack Overflow帖子中可以看到一些方便的工具.
JAPICC似乎相当不错.
然后,我
mvn dependency:tree用来确定我实际使用的Jackson版本(问题2:是否有一种自动方式询问maven正在使用哪个版本的jar,而不是梳理树输出?)
这maven-dependency-tree绝对是要走的路,但是你可以从范围开始过滤掉,只能得到你真正想要的东西,使用它的includes选项如下:
mvn dependency:tree -Dincludes=<groupId>
Run Code Online (Sandbox Code Playgroud)
注意:您还includes可以在表单中提供更多信息groupId:artifactId:type:version或使用通配符*:artifactId.
这似乎是一个小小的提示,但在具有许多依赖性的大型项目中,缩小其输出量是非常有帮助的.通常情况下,只要它groupId应该足够作为过滤器,*:artifactId但如果您正在寻找特定的依赖项,则可能是最快的.
如果您对依赖项列表(不是树)感兴趣,也按字母顺序排序(在许多情况下非常方便),那么以下内容也可能有所帮助:
mvn dependency:list -Dsort=true -DincludeGroupIds=groupId
Run Code Online (Sandbox Code Playgroud)
问题3:当依赖解析发生时,maven如何在着色罐中使用库?和其他任何一样?
通过阴影罐你可能意味着:
有没有人有他们使用的资源?
通常,您应该很好地理解Maven如何处理依赖关系并使用它提供的资源(其工具和机制).以下一些要点:
dependencyManagement绝对是本主题的切入点:在这里,您可以处理Maven依赖性调解,影响其对传递依赖性的决定,它们的版本,范围.一个重要的一点是:您添加的dependencyManagement内容不会自动添加为依赖项.dependencyManagement只有在项目的某个依赖项(如pom.xml文件中声明或通过传递依赖项)与其中一个条目匹配时才会考虑它,否则它将被简单地忽略.它是一个重要的组成部分,pom.xml因为它有助于管理依赖关系及其传递图,这就是为什么经常在父poms中使用:你只想处理一个并以集中方式处理哪个版本,例如,log4j你想要在所有的你的Maven项目,你在一个共同的/共享的父pom中声明它,dependencyManagement并确保它将被这样使用.集中化意味着更好的治理和更好的维护.dependencysection对于声明依赖项非常重要:通常,您应该在此处仅声明所需的直接依赖项.一个好的重击规则是:在这里声明compile(默认)范围只是你import在代码中实际用作语句的内容(但是你经常需要超越它,例如,运行时需要的JDBC驱动程序,并且从未在代码中引用它,它然后将在runtime范围内).还要记住:声明的顺序很重要:第一个声明的依赖关系会在与传递依赖冲突的情况下获胜,因此通过重新声明一个依赖关系,您可以有效地影响依赖关系中介.exclusions依赖关系来处理传递依赖:如果可以的话,使用dependencyManagement和顺序dependencies.滥用exclusions维护更加困难,只有在你真正需要时才使用它.此外,添加时exclusions总是添加XML注释,解释原因:您的团队成员或/和您未来的自我将会欣赏.scope若有所思.将default(compile)范围用于编译和测试所需的内容(例如loga4j),test仅用于(并且仅用于)测试中使用的内容(例如junit),请注意provided目标容器已提供的范围(例如servlet-api),runtime仅将范围用于运行时所需的内容,但不应使用它进行编译(例如JDBC驱动程序).不要使用system示波器,因为它只会带来麻烦(例如它没有与最终的工件一起打包).[<version>]表达式是最强的,但您很少需要它.property作为version库的族元素的占位符,以确保您有一个集中的位置来版本化一组依赖项,这些依赖项都具有相同的版本值.一个典型的例子是用于多个依赖项的属性spring.version或hibernate.version属性.同样,集中化意味着更好的治理和维护,这也意味着更少的头痛和更少的地狱.pom.xml文件管理某组依赖项.SNAPSHOT依赖项(或尽可能少).如果您确实需要,请确保您永远不会使用SNAPSHOT依赖项发布:否则构建再现性将处于高危险状态.pom.xml文件的完整层次结构,help:effective-pom在检查有效时使用可能非常有用dependencyManagement,dependencies并且properties就最终的依赖关系图而言.maven-dependency-plugin在排除故障时非常有用,但也maven-enforcer-plugin有帮助.以下是一些值得一提的例子:以下示例将确保没有人(您,您的团队配合,您自己的未来)将能够在compile范围内添加一个众所周知的测试库:构建将失败.它确保junit永远不会达到PROD(与您一起打包war,例如)
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1<.version>
<executions>
<execution>
<id>enforce-test-scope</id>
<phase>validate</phase>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<bannedDependencies>
<excludes>
<exclude>junit:junit:*:*:compile</exclude>
<exclude>org.mockito:mockito-*:*:*:compile</exclude>
<exclude>org.easymock:easymock*:*:*:compile</exclude>
<exclude>org.powermock:powermock-*:*:*:compile</exclude>
<exclude>org.seleniumhq.selenium:selenium-*:*:*:compile</exclude>
<exclude>org.springframework:spring-test:*:*:compile</exclude>
<exclude>org.hamcrest:hamcrest-all:*:*:compile</exclude>
</excludes>
<message>Test dependencies should be in test scope!</message>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
Run Code Online (Sandbox Code Playgroud)
看看这个插件提供的其他标准规则:在出现错误情况时,许多可能对破坏构建很有用:
同样,公共父pom可以包括多个这些机制(dependencyManagement,enforcer插件,依赖项系列的属性),并确保遵守某些规则.您可能无法涵盖所有可能的情景,但它肯定会降低您感知和体验的地狱程度.
| 归档时间: |
|
| 查看次数: |
4273 次 |
| 最近记录: |