I don't know if you have encountered problems such as "NoSuchMethodError" or "ClassNotFoundException" when using Maven, or even Java classes where these problems occur you haven't heard of. To figure out the reason for this, we have to learn Maven's handling mechanism for dependency conflicts.
Maven uses a "nearest wins strategy" to handle dependency conflicts, that is, if a project ends up depending on multiple versions of the same artifact, the version closest to the project in the dependency tree will be used. Let's look at a practical example.
Please download the github source code of this article: https://github.com/davenkin/maven-dependency-conflict-demo
We have a web application resolve-web, which depends on project-A and project-B, project-A depends on version 1.0 of project-common and calls the sayHello() method in it. project-B depends on project-C, which in turn depends on version 2.0 of project-common and calls the sayGoodBye() method in it. The 1.0 and 2.0 versions of project-common are different. 1.0 contains the sayHello() method, while 2.0 contains the sayHello() and sayGoodBye() methods. The dependencies of the entire project are as follows:
According to Maven's transitive dependency mechanism, resolve-web will depend on both versions 1.0 and 2.0 of project-common, which creates a dependency conflict. And according to the most recent winning strategy, Maven will choose the 1.0 version of project-common as the final dependency. This is different from Gradle, which by default will choose the latest version as the winning version. And for Maven, version 1.0 wins because version 1.0 of proejct-common is closer to resolve-web in the dependency tree than version 2.0. Execute "mvn dependency:tree -Dverbose" in resolve-web to see the dependencies of resolve-web:
[INFO] resolve-web:resolve-web:war:1.0-SNAPSHOT [INFO] +- junit:junit:jar:3.8.1:test [INFO] +- project-B:project-B:jar:1.0:compile [INFO] | \- project-C:project-C:jar:1.0:compile [INFO] | \- (project-common:project-commmon:jar:2.0:compile - omitted for conflict with 1.0) [INFO] +- project-A:project-A:jar:1.0:compile [INFO] | \- project-common:project-commmon:jar:1.0:compile [INFO] \- javax.servlet:servlet-api:jar:2.4:provided
As can be seen from the above, project-common:project-commmon:jar:2.0 is ignored. At this time, only the 1.0 version of project-common will be included in the war package of resolve-web, so the problem comes. Since version 1.0 of project-common does not include the sayGoodBye() method, which is required by project-C, a "NoSuchMethodError" will appear at runtime. (Please reproduce the error message according to the steps in the README.md in the github project of this article.)
For this problem caused by dependency conflicts, we have two solutions.
方法1:显式加入对project-common 2.0版本的依赖。先前的2.0版本不是离resolve-web远了点吗,那我们就直接将它作为resolve-web的依赖,这不就比1.0版本离resolve-web还近吗?在resove-web的pom.xml文件中直接加上对project-common 2.0 的依赖:
<dependency> <groupId>project-common</groupId> <artifactId>project-commmon</artifactId> <version>2.0</version> </dependency>
方法2:resolve-web对project-A的dependency声明中,将project-common排除掉。在resolve-web的pom.xml文件中修改对project-A的dependency声明:
此时再在resolve-web中执行"mvn dependency:tree -Dverbose",结果如下:
...... [INFO] resolve-web:resolve-web:war:1.0-SNAPSHOT [INFO] +- junit:junit:jar:3.8.1:test [INFO] +- project-B:project-B:jar:1.0:compile [INFO] | \- project-C:project-C:jar:1.0:compile [INFO] | \- project-common:project-commmon:jar:2.0:compile [INFO] +- project-A:project-A:jar:1.0:compile [INFO] \- javax.servlet:servlet-api:jar:2.4:provided ......
The 1.0 version of project-common is no longer included in the dependency tree at this time.
In addition, we can also declare the dependency on project-common as optional in project-A, optional means non-transitive. At this time, when project-A is referenced in resolve-web, Maven will not regard project-common as Transitive dependencies are added automatically, unless another project (such as project-B) declares a transitive dependency on project-common or we explicitly declare a dependency on project-common in resolve-web (method 1).
Reprinted from: https://www.cnblogs.com/davenkin/p/advanced-maven-resolve-dependencies-conflicts.html
optimization dependencies
can be summarized into three commands
mvn dependency:list
Indicates the list of dependencies, the maven eclipse plug-in has been implemented, there is a graphical display, in the dependencies page of pom.xml
mvn dependency:tree
Indicates the dependency list, the maven eclipse plug-in has been implemented, there is a graphical display, in the dependency hierarchy page of pom.xml
mvn dependency:analyze
Find dependencies that are not used but explicitly declared in compilation and testing
Reprinted from: https://blog.csdn.net/lastsweetop/article/details/8493475