Summary record of Maven multi module and dependency conflict

Time:2020-11-24

catalog

Summary record of Maven multi module and dependency conflict

preface:

Today, I learned and summarized the relevant knowledge points of maven, and found that some basic things would be forgotten. Here is a summary of some problems that may be encountered in daily work.

Idea how to create Maven multi module project

First of all, how many modules are above?

In a word, a parent module is used as a version control sub module, and the sub module is responsible for accessing to the parent module as the whole project process.

Several ways of multi module project management:

  1. Divide a single module into multiple sub modules. For example, the three-tier MVC architecture is divided into XXX service, XXX Dao and XXX model. However, I feel that this method is quite different. At present, there are more business modules to be split, and it is not easy to use when migrating to microservices such as springcloud or Dubbo.
  2. According to the business module split, this mode is used more and more often.

Create a multi module project (idea2019.3.3)

Create a parent POM project:

  1. Open idea and selectcreate new project

Summary record of Maven multi module and dependency conflict

  1. Select the Maven project without selecting any preload settings

Summary record of Maven multi module and dependency conflict

  1. The parent POM is configured as follows:

Summary record of Maven multi module and dependency conflict

  1. deletesrccatalog

Summary record of Maven multi module and dependency conflict

Create a sub module and import it into the parent POM

  1. Similarly, right-click the project project and selectnew module, and then selectmavenIn this case, the parent module and the corresponding sub module name will appear

Summary record of Maven multi module and dependency conflict

  1. At this time, it is found in the parent module that the content of the child module has been introduced

Summary record of Maven multi module and dependency conflict

Differences between child and parent modules:

father pom.xml Document content:

<groupId>org.zxd</groupId>
<artifactId>taglib</artifactId>
<packaging>pom</packaging>
<version>1.0.0</version>

<modules>
    <module>taglib-core</module>
</modules>

It is divided into two parts. One part is the declaration of the parent POM, including gourpid, artifact ID, and packing methodMust be POMBecause of theAggregation modelAt the same time, specify the version number in the parent POM. If the child module does not fill in version, the version number of the parent POM will be used by default

<modules>
    <module>taglib-core</module>
</modules>

The above shows the content of the currently introduced sub module

son pom.xml Document content:

<! -- referenced from parent POM -- >
<parent>
    <artifactId>taglib</artifactId>
    <groupId>org.zxd</groupId>
    <version>1.0.0</version>
</parent>
<! -- the packaging method is jar package -- >
<packaging>jar</packaging>
<modelVersion>4.0.0</modelVersion>

<artifactId>taglib-core</artifactId>
<version>1.0.0</version>

The sub modules depend on each other

In the following POM, the corresponding parent module dependency can be introduced into any child module

Pay attention to the<parent>This tag will inherit recursively, so you should be careful not to introduce different versions of dependencies to child dependencies and dependencies, which may lead to conflicts

<dependency>
    <groupId>org.zxd</groupId>
    <artifactId>taglib-core</artifactId>
    <version>1.0.0</version>
    <! -- you need to comment out the compiled scope here -- >
    <!--<scope>compile</scope>-->
</dependency>

Transform the above project into a spring boot multi module project

Modify the parent POM file:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.0</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

Parent points tospringboot-started

The child module only needs to introduce the contents of the parent POM

Spring boot Maven plugin problem

When packaging a spring boot project, you need to use the following plug-ins:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

If you use Maven to build a multi module project, do not put this plug-in into the parent POM. Otherwise, if there is a sub module that is not a spring boot application, there will be an error in packaging.Only add the plug-in to a sub module that is a spring boot project

Maven dependency conflict problem:

The transmission principle of dependence:

  1. Shortest path principle
  2. First to declare principle

Dependency introduction strategy of maven

The shortest path principle:

I have the following two dependency jar packages, a and B. they both introduce the dependency C. at this time, if there is a reference as follows

A -> C(3.3)

B -> A(3.3)

B -> C(3.4)

At this point, if B is packaged, the version number will be 3.4. However, if B removes the dependency of C, it will be the transitive dependency of a > C, which is very simple

verification:

  1. I assume that I have a web package that introduces common-lang3, version 3.4
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>
  1. At this time, a public package is introduced, which also contains this reference:
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.3</version>
</dependency>
  1. If version 3.4 is referenced locally at this time, it is version 3.4. Otherwise, version 3.3 will die, regardless of the declaration order

First declaration principle:

If the addressing paths of the two jar packages are the same, who should declare first and introduce the first

verification:

The following two dependency assignments correspond to two modules. The module introducing the module is tentatively designated asCmodular.

<! -- introduce core package content -- >
<dependency>
    <groupId>org.zxd</groupId>
    <artifactId>taglib-core</artifactId>
    <version>1.0.0</version>
    <!--            <scope>compile</scope>-->
</dependency>
<! -- introduce the content of DB package -- >
<dependency>
    <groupId>org.zxd</groupId>
    <artifactId>taglib-db</artifactId>
    <version>1.0.0</version>
</dependency>

heretaglib-coreThe dependency version in is as follows, tentatively asAmodular:

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-client</artifactId>
    <version>2.5.0</version>
</dependency>

andtaglib-dbThe dependency version in is as follows, tentatively asBmodular:

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-client</artifactId>
    <version>4.0.1</version>
</dependency>

At this time, package the whole web project, and you can see that the versions in the web project are as follows:

Summary record of Maven multi module and dependency conflict

It can be clearly seen that if the introduction relationship is like this:

C -> A,B

A -> curator-client 2.5

B -> curator-client 4.1

The final effect of such a link is C > a > curator client 2.5

This has led to a lot of situations in which wecompileandfunctionThere is no problem at all,It’s even possible that packing is normalBut at the end of the run, an error is reported suddenly. Be careful of this problem of version dependence. Fortunately, managers are responsible for controlling version dependency in general company projects. This kind of error is considered as a low-level error. However, in the era of rapid development of frameworks, the issue of version control of dependency management still needs to be paid attention to!!!

How to solve the problem of dependency conflict

Locking version method

In general, we will manage it in the parent POM file. You can use the<dependencyManagement>This tag is used to manage the version dependency of all child modules. If a child module specifies its own version, it is found that the package printed is still the version specified by the parent POM. Version management is used as follows:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-client</artifactId>
            <version>4.1.0</version>
        </dependency>
    </dependencies>
</dependencyManagement>

Locking version method can break the principle of two dependency passing, with the highest priority

Version locking can exclude some exclude tags. Jar packages with different versions for different modules do not conform to the specification, so this method is more secure

When will jar package conflict occur

This problem can only be caused by the incompatibility of jar packages with higher versions or the addition of some APIs that are not available in lower versions

How to find and find jar package conflicts?

1. Use the Maven view tool of idea

Use a diagram to illustrate:

Summary record of Maven multi module and dependency conflict

This tool can be used to view which module the dependency is repeatedly referenced in. At the same time, if there is a conflict, the red line will be displayed. This view is very intuitive, which can help the dependency manager to deal with the problem of dependency repeated reference or inconsistent reference version<exclude>operation

2. Idea Maven Helperplug-in unit

Summary record of Maven multi module and dependency conflict

How to use it?

After installation, find one at random pom.xml File, follow the following legend prompts to operate, for the conflict content, right-clickexcludeYou can exclude dependencies:

Summary record of Maven multi module and dependency conflict

After eliminating dependencies, click theRefresh UIRefresh the UI interface:

Summary record of Maven multi module and dependency conflict

3. Maven command tool:

mvn dependency:tree -DverboseSometimes, if we don’t have an idea, we can use this command to process it. The execution results are as follows:

PS: don’t omit it here-DverboseParameter, otherwisecan’tDisplay byignoreThe bag of

or:curator-client:jar:4.1.0:compile
[INFO] |  |  +- org.apache.zookeeper:zookeeper:jar:3.5.4-beta:compile
[INFO] |  |  |  +- commons-cli:commons-cli:jar:1.2:compile
[INFO] |  |  |  +- log4j:log4j:jar:1.2.17:compile
[INFO] |  |  |  +- org.apache.yetus:audience-annotations:jar:0.5.0:compile
[INFO] |  |  |  \- io.netty:netty:jar:3.10.6.Final:compile
[INFO] |  |  +- com.google.guava:guava:jar:20.0:compile
[INFO] |  |  \- org.slf4j:slf4j-api:jar:1.7.30:compile
[INFO] |  +- commons-codec:commons-codec:jar:1.15:compile
[INFO] |  +- commons-collections:commons-collections:jar:3.2.2:compile
[INFO] |  +- commons-beanutils:commons-beanutils:jar:1.9.4:compile
[INFO] |  +- commons-configuration:commons-configuration:jar:1.10:compile
[INFO] |  |  \- commons-lang:commons-lang:jar:2.6:compile

Generally speaking, it is relatively intuitive, very convenient and easy to use.

How to write a clean dependencyPOMfile

  • Try to define it in the parent POM<dependencyManagement>, to manage some dependent versions of the project, so as to solve certain conflicts to a great extent
  • Minimum dependence on jar package principle
  • usemvn dependency:analyze-onlyThe command is used to detect dependencies that are declared but not used. If some of them are declared by yourself, try to remove them
  • usemvn dependency:analyze-duplicateThe command is used to analyze and clean up duplicate defined dependencies

dependency:analyze-onlycommand

In idea-TerminalInside, you can see that the corresponding dependencies are downloaded

Summary record of Maven multi module and dependency conflict

After the execution, my running results are as follows. The reason for the error is that when packing, I go to the alicloud warehouse to look for dependencies by default. Here we need to configure:

Summary record of Maven multi module and dependency conflict

[ERROR] Failed to execute goal on project taglib-web: Could not resolve dependencies for project org.zxd:taglib-web:war:1.0.0: The following artifacts could not be resolved: org.zxd:
taglib-core:jar:1.0.0, org.zxd:taglib-db:jar:1.0.0: Failure to find org.zxd:taglib-core:jar:1.0.0 in http://maven.aliyun.com/nexus/content/repositories/central/ was cached in the loc
al repository, resolution will not be reattempted until the update interval of alimaven has elapsed or updates are forced -> [Help 1]

This basically means that the corresponding dependency import cannot be found in the alicloud warehouse.

The solutions are as follows:

Find theapache-maven-3.6.3\confBelowsetting.xml, find the following configuration:

<!-- localRepository
   | The path to the local repository maven will use to store artifacts.
   |
   | Default: ${user.home}/.m2/repository
  <localRepository>/path/to/local/repo</localRepository>
  -->
<! -- configure the location of local warehouse here -- >
  <localRepository>D:\soft\apache-maven-3.6.3\rep</localRepository>

At this point, execute again:dependency:analyze-onlycommand

[INFO] --- maven-dependency-plugin:3.1.2:analyze-only (default-cli) @ taglib-web ---
[WARNING] Unused declared dependencies found:
[WARNING]    org.zxd:taglib-core:jar:1.0.0:compile
[WARNING]    org.apache.commons:commons-lang3:jar:3.4:compile
[WARNING]    org.springframework.boot:spring-boot-starter-web:jar:2.4.0:compile
[WARNING]    org.springframework.boot:spring-boot-starter-test:jar:2.4.0:test
[WARNING]    org.neo4j.driver:neo4j-java-driver:jar:1.5.0:compile
[WARNING]    commons-codec:commons-codec:jar:1.10:compile
[WARNING]    commons-collections:commons-collections:jar:3.2.2:compile
[WARNING]    commons-beanutils:commons-beanutils:jar:1.9.4:compile
[WARNING]    commons-configuration:commons-configuration:jar:1.10:compile
[WARNING]    commons-fileupload:commons-fileupload:jar:1.3:compile
[WARNING]    commons-logging:commons-logging:jar:1.2:compile
[WARNING]    org.apache.httpcomponents:httpclient:jar:4.4.1:compile
[WARNING]    org.apache.poi:poi-ooxml:jar:3.17:compile
[WARNING]    org.mybatis:mybatis:jar:3.4.0:compile
[WARNING]    org.mybatis:mybatis-spring:jar:1.3.0:compile
[WARNING]    com.github.pagehelper:pagehelper:jar:5.1.2:compile

mvn dependency:analyze-duplicatecommand

[INFO] No duplicate dependencies found in <dependencies/> or in <dependencyManagement/>

If there is no other information, it means that there is no duplicate dependency introduced