然后,我查看 Jackson 文档,了解该方法的添加或删除时间。这通常很乏味,因为我手动检查每个版本的api文档(问题1:有没有更好的方法?
要检查API(中断)兼容性,有几个工具可以自动分析jar并为您提供正确的信息。从这个Stack Overflow帖子中,有一些方便的工具有很好的提示。
JAPICC似乎相当不错。
然后,我用来弄清楚我实际使用的是哪个版本的Jackson(问题2:有没有一种自动的方式来询问专家正在使用哪个版本的jar,而不是梳理树输出?mvn dependency:tree
这绝对是要走的路,但是您可以从一开始就过滤掉范围,只获取您实际要查找的内容,使用其包含
选项,如下所示:maven-dependency-tree
mvn dependency:tree -Dincludes=<groupId>
注意:您还可以在表单中为该选项提供更多信息,或使用通配符,例如.includes
groupId:artifactId:type:version
*:artifactId
这似乎是一个小小的提示,但在具有许多依赖项的大型项目中,缩小其输出范围会有很大的帮助。通常,简单地说,作为过滤器应该足够了,如果您正在寻找特定的依赖项,这可能是最快的。groupId
*:artifactId
如果您对按字母顺序排序的依赖项列表(不是树)感兴趣(在许多情况下非常方便),那么以下内容也可能有所帮助:
mvn dependency:list -Dsort=true -DincludeGroupIds=groupId
问题 3:当发生依赖关系解析时,maven 如何使用着色 jar 中的库?与其他任何一样?
通过阴影罐,你可能意味着:
-
胖罐子,这也将其他罐子带入类路径。在这种情况下,它们被视为一个依赖项,Maven 依赖项中介的一个单元,其内容将成为项目类路径的一部分。一般来说,你不应该把胖罐作为你的依赖关系的一部分,因为你无法控制它带来的打包库。
-
带有阴影(重命名)包的 jar。在这种情况下 - 再次 - 就Maven依赖性中介而言,没有控制:它是一个单元,一个罐子,基于其GAVC(GroupId,ArtifactId,Version,Classifier),这使得它独一无二。然后,它的内容将添加到项目类路径中(根据依赖项范围,但由于其包已重命名,因此可能会遇到难以处理的冲突。同样,您不应该将重命名的包作为项目依赖项的一部分(但通常您无法知道这一点)。
有没有人拥有他们使用的任何资源?
通常,您应该很好地了解 Maven 如何处理依赖项以及使用它提供的资源(其工具和机制)。以下是一些要点:
-
依赖关系管理
绝对是本主题的切入点:在这里,您可以处理 Maven 依赖关系中介,影响其对传递依赖关系、版本和范围的决策。重要的一点是:您添加到的内容不会自动添加为依赖项。 只有在项目的某个依赖项(如在文件中声明或通过传递依赖项)与其某个条目匹配时才被考虑在内,否则它将被简单地忽略。这是其中很重要的一部分,因为它有助于管理依赖关系及其传递图,这就是为什么经常在父pom中使用的原因:你只想处理一个版本,并以集中的方式处理哪个版本,例如,你想在所有Maven项目中使用,你在一个公共/共享的父pom中声明它,并确保它将被这样使用。集中化意味着更好的治理和更好的维护。dependencyManagement
dependencyManagement
pom.xml
pom.xml
log4j
dependencyManagement
-
依赖关系
部分对于声明依赖关系很重要:通常,您应在此处仅声明所需的直接依赖关系。一个好的 thump 规则是:在这里声明为(默认)范围,只声明您在代码中实际用作语句的内容(但是您通常需要超越它,例如,运行时需要的 JDBC 驱动程序,并且永远不会在代码中引用,然后它将在范围内)。还要记住:声明的顺序很重要:在与传递依赖关系发生冲突的情况下,第一个声明的依赖项获胜,因此,通过重新声明依赖项,您可以有效地影响依赖项中介。compile
import
runtime
-
不要滥用
依赖关系中的排除来处理传递依赖关系:如果可以的话,它的使用和顺序。滥用使维护更加困难,只有在您真正需要时才使用它。此外,在添加时,请始终添加一个XML注释来解释原因:您的队友或/和您未来的自己会欣赏。dependencyManagement
dependencies
exclusions
exclusions
-
深思熟虑地使用依赖项
范围
。将默认 () 作用域用于编译和测试(例如),仅(且仅)用于测试中使用的内容(例如),注意目标容器已提供的内容的范围(例如),仅将作用域用于运行时所需的内容,但永远不要使用它进行编译(例如 JDBC 驱动程序)。不要使用 scope,因为它只会带来麻烦(例如,它没有与最终工件一起打包)。compile
loga4j
test
junit
provided
servlet-api
runtime
system
-
不要使用版本范围,除非出于特定原因,并且请注意,默认情况下指定的版本是最低要求,否则表达式是最强的,但您很少需要它。
[<version>]
-
使用 Maven
属性
作为库系列的版本
元素的占位符,以确保您有一个集中的位置用于对一组依赖项进行版本控制,这些依赖项都具有相同的版本值。一个典型的示例是用于多个依赖项的 or 属性。同样,集中化意味着更好的治理和维护,这也意味着更少的头痛和更少的地狱。spring.version
hibernate.version
-
在提供时,导入 BOM 作为上述点的替代方法,并更好地处理依赖项系列(例如 jboss),将一组特定依赖项的管理委托给另一个文件。
pom.xml
-
不要(ab)使用
快照
依赖项(或尽可能少地使用)。如果你真的需要,确保你永远不会使用依赖关系发布:否则,构建可重复性将处于很高的危险之中。SNAPSHOT
-
在进行故障排除时,请始终检查文件的完整层次结构,使用
help:effective-pom
在检查 effective 时可能非常有用,并且就最终的依赖关系图而言。pom.xml
dependencyManagement
dependencies
properties
-
使用其他一些Maven插件来帮助你进行治理。这在故障排除过程中确实很有帮助,但也提供了帮助。以下是一些值得一提的例子:
maven-dependency-plugin
maven-enforcer-plugin
以下示例将确保没有人(您、您的队友、您未来的自己)能够在范围内添加众所周知的测试库:构建将失败。它确保永远不会到达PROD(与您的,例如打包在一起)compile
junit
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>
看看这个插件提供的其他标准规则:在错误的情况下,许多规则可能有助于破坏构建:
同样,一个共同的父 pom 可以包含多个这些机制(强制器插件、依赖项系列的属性),并确保遵守某些规则。你可能不会涵盖所有可能的场景,但它肯定会降低你所感知和体验的地狱程度。dependencyManagement