6
头图

The basic knowledge of maven is recorded here. On the one hand, it consolidates the knowledge that I have learned, and on the other hand, I hope that I can provide some help to those who have the same confusion.

1. Introduction to maven

Maven is a project management tool, it contains a project object model POM (Project Object Model), a set of standard collections, a project lifecycle (Project Lifecycle), a dependency management system (Dependency Management System) and used to run the definition in The logic of the plugin's goal in the phase of the life cycle. When you use Maven, you use a clearly defined POM to describe your project, and then Maven can apply cross-cutting logic, which comes from a set of shared (or custom) plugins.

The core of Maven doesn't actually do practical things. It doesn't understand anything except parsing some XML documents, managing the life cycle and plug-ins. Maven is designed to delegate the main responsibilities to a set of Maven plugins, which can influence the Maven life cycle and provide access to goals. The vast majority of Maven actions occur in the goals of the Maven plugin, such as compiling source code, packaging binary code, publishing sites, and other build tasks. The Maven you downloaded from Apache doesn't know how to package WAR files or how to run unit tests. Most of Maven's intelligence is implemented by plugins, which are obtained from the Maven repository. In fact, the first time you run a mvn install with a brand new Maven installation, it will download most of the core Maven plugins from the central Maven repository. This is not just a technique for minimizing the size of the Maven distribution package, it also allows you to upgrade the plugin to improve your project's ability to build. The fact that Maven obtains dependencies and plugins from remote repositories allows for global reuse of the build logic.

Use the following command to view the detailed information of the specified plug-in:

mvn help:describe -Dplugin=install -Dfull

2. maven life cycle

1. Maven default life cycle

Life cycle stagedescribe
validateVerify that the project is correct and all necessary information for a complete build is available
generate-sourcesGenerate all the source code that needs to be included in the compilation process
process-sourcesProcessing source code, such as filtering some values
generate-resourcesGenerate all resource files that need to be included in the package
process-resourcesCopy and process the resource files to the target directory, ready to package
compileCompile the source code of the project
process-classesPost-process the compiled class files, such as bytecode enhancement for Java classes
generate-test-sourcesGenerate all test source code included in the test compilation process
process-test-sourcesProcessing test source code, such as filtering some values
generate-test-resourcesGenerate resource files needed for testing
process-test-resourcesCopy and process test resource files to the test target directory
test-compileCompile the test source code to the test target directory
testRun tests using a suitable unit testing framework, these tests do not need to be packaged or released
prepare-packageBefore the actual packaging, perform some necessary operations to prepare for packaging
packagePackage the compiled code into a distributable format, such as JAR, WAR
pre-integration-testPerform some actions required before the integration test runs. Such as establishing the environment required for integration testing
integration-testIf necessary, process the package and publish to an environment where integration tests can run
post-integration-testPerform some actions required after the integration test runs. Such as cleaning up the integrated test environment.
verifyPerform all checks to verify that the package is valid and meets quality specifications
installInstall the package to the local warehouse to prepare other local projects as dependencies
deployInstall the package to a remote warehouse and share it with other developers and projects

The commonly used life cycles are marked in the above table, and the life cycle of maven in the corresponding idea is as follows:

image.png

2. What happened when mvn package was executed

image.png

We can bind the goal of the plug-in to the life cycle phase of maven, execute the mvn package command, and as Maven moves forward step by step along the life cycle, it will run all the goals bound to each phase.

Three. Maven project dependency

Maven can manage internal and external dependencies. Internal dependency refers to the dependency between various modules within a maven project. For example, the service module in a three-tier web project depends on the model module or the persistence layer module; external dependency refers to the dependency on third-party libraries, such as spring and mybatis. And other related dependencies.

1. Scope of dependence

When specifying dependency dependencies in the pom.xml file, you can specify the dependent scope range. The range can control which dependencies classpath and which dependencies are included in an application. Let's look at each range in detail:

  • compile (compilation range)

    compile is the default range . If a scope is not provided, the dependent scope is the compilation scope. Compilation range dependencies classpath , and they will also be packaged.

  • provided

    provided dependency is only used when the dependency is provided by JDK For example, if you develop a web application, you may compile classpath needs to be available in Servlet API to compile a servlet , but you do not want to include this in the packaged WAR in Servlet API , this Servlet API JAR of your application server or servlet The container is provided. provided range are available at compile classpath (not at runtime), they are not transitive and will not be packaged.

  • runtime (runtime range)

    runtime dependencies are required at runtime, but not required at compile time. For example, you may only need the JDBC API JAR interface when compiling, but only need the JDBC driver implementation when running.

  • test (test range)

    Test scope dependencies are not required during general compilation and runtime. They are only available during test compilation and test runtime phases.

  • system (system-wide)

    The system scope dependency is similar to provided, but you must explicitly provide a path to the JAR file in the local system. This is done to allow compilation based on local objects, which are part of the system class library. Such a component should always be available, and Maven will not look for it in the warehouse. If you set a dependency scope to the system scope, you must also provide a systemPath element. Note that this range is not recommended (you should always try to reference dependencies from public or custom Maven repositories).

    scope valueEffective range (compile, runtime, test)Dependency passexample
    compile (default)allYesspring-core
    providedcompile、testnoservlet-api
    runtimeruntime、testYesJDBC driver
    testtestnoJunit
    systemcompile、testYesNot recommended

2. Optional dependencies

<dependency> dependency in the pom.xml file, the dependency can be declared as an optional dependency <optional>true<optional> If the dependent class library in the project contains optional dependencies, we need to display and specify the required optional dependencies when using it.

3. Transitive dependency

Transitive dependency is the dependency on a dependency. If project-a depends on project-b, which in turn depends on project-c, then project-c is considered to be a transitive dependency of project-a. If project-c depends on project-d, then project-d is also considered as a transitive dependency of project-a. Part of the advantage of Maven is due to its ability to manage transitive dependencies and to help developers shield all the details of tracking dependencies during compilation and runtime. You can only rely on some packages such as Spring Framework without worrying about all the dependencies of Spring Framework. Maven will automatically manage it for you, and you don't need to learn the configuration in detail by yourself.

How does Maven accomplish this? It establishes a dependency graph and handles some conflicts and overlaps that may occur. If Maven sees that there are two projects that depend on the same groupId and artifactId, it will automatically select the latest version of the dependency. Although this sounds convenient, in some border cases, transitive dependencies can cause some configuration problems. In this case, you can use <exclusion> dependency exclusion.

<exclusion> dependency exclusion can be used in the following situations:

  1. Exclude dependencies that are introduced through transitive dependencies but are not used in the project
  2. Exclude dependencies already provided by the runtime container
  3. Exclude API dependencies that may have multiple implementations
  4. There are multiple versions of dependencies, exclude the dependency you don’t want to use

4. Dependency Management

In a complex maven project with many modules, if many modules use the same dependency, such as MySQL database-driven dependency, you need to list the dependency version independently in each module. If you need to upgrade to a new You will encounter problems with the version. Since these version numbers are scattered in your project tree, you need to manually modify each pom.xml that references the dependency to ensure that the version number in each place is changed. So how to solve this problem?

maven provides dependencyManagement elements to the unified management rely on the version number, use pom.xml in dependencyManagement element allows you to reference a dependency without explicit version number listed, maven will walk up the parent-child hierarchy in the sub until you find a A project with dependencyManagement elements, and then it will be used in this

The version number specified in the dependencyManagement

Note that if the subproject defines a version version , it will override dependencyManagement element of the top POM. Only when the subproject does not directly declare a version, the version defined by dependencyManagement

The dependencies defined in the dependencyManagement of the top-level pom.xml file will not be imported if there is no display reference in the sub-projects, but the dependencies defined in the dependencies pom.xml will be imported by all sub-projects. In order not to add some unnecessary dependencies, Using dependencyManagement allows you to unify and centralize the management of dependency versions without adding dependencies that will be inherited by all sub-projects. In other words, the dependencyManagement element is the same as an environment variable, allowing you to declare a dependency anywhere under a project without specifying a version number.

Four. Maven built-in properties

1. maven properties

You can pom.xml files or resource files, which are Maven Resource by the filtering feature of the 060fa8c2a5a9f0 plug-in. An attribute is always included in ${} . For example, to quote the project.version attribute, you need to write ${project.version} like this. There are some implicit properties in any Maven project. These implicit properties are:

  • project.*

    You can use the project.* prefix to refer to any value pom.xml

  • settings.*

    You can use the settings.* prefix to refer to the value in the ~/.m2/settings.xml

  • env.*

    You can use the env.* prefix to refer to the values of PATH and M2_HOME

  • System properties

    Any property that can be obtained through the System.getProperty() method can be referenced as a maven property.

You can use the mvn help:system command to view all environment variables.

In addition to the above implicit attributes, users can also use <properties> custom attributes.

2. Common attributes of pom.xml file

${project.groupId}:项目的groupId.
${project.artifactId}:项目的artifactId.
${project.version}:项目的version,于${version}等价 
${project.basedir}:表示项目根目录,即包含pom.xml文件的目录;  
${project.build.sourceDirectory}:项目的主源码目录,默认为src/main/java/.
${project.build.testSourceDirectory}:项目的测试源码目录,默认为/src/test/java/.
${project.build.directory}:项目构建输出目录,默认为target/.
${project.outputDirectory}:项目主代码编译输出目录,默认为target/classes/.
${project.testOutputDirectory}:项目测试代码编译输出目录,默认为target/testclasses/.
${project.build.finalName}:项目打包输出文件的名称,默认为${project.artifactId}-${project.version}

3. Setting.xml file attributes

And pom attribute the same token, the user can be used to settings. the beginning of the property references setting.xml XML element values file.

${settings.localRepository} represents the address of the local warehouse

4. Custom Properties

Custom attributes: maven attributes defined under the <properties> pom.xml

<properties>
    <spring>5.2.13.RELEASE</spring>
</properties>

You can use custom attributes in other places:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring}</version>
</dependency>

Five. POM best practices

1. Rely on classification

If you have a set of dependencies that are logically grouped together, you can create a pom packaged as 060fa8c2a5af7c to group these dependencies together. For example, create a dependencies called 060fa8c2a5af80. This module only contains a pom.xml file, which is used to categorize and manage the version numbers of some public dependencies. Note that the packaging type of this module is specified as: <packaging>pom</packaging> .

For example, it is also used dubbo dubbo-dependencies-bom called 060fa8c2a5afc4. There is only one pom.xml file in the module, as shown in the following figure:

image.png

In dubbo-dependencies-bom , the parent of pom.xml , it is introduced and used in the following way:

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-dependencies-bom</artifactId>
                <version>${project.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

2. The problem of resource filtering

In the above maven life cycle of one we know, maven will resources:resources target bound to process-resources life cycle stages, by default resources:resources action goal is to src/main/resources copy the files in the directory to target/classes directory. In addition to copying files to the output directory, the resources:resources target can also use a filter to replace the symbol variable ( ${variable name}) in the resource file with the value pointed to by the variable. You can use the following method to enable the filter function :

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
        
            <!--使用 <excludes> 排除 src/main/resources 目录下的 test.txt 文件 -->
            <excludes>
                <exclude>test.txt</exclude>
            </excludes>

            <!--
            开启过滤器功能,开启之后就可以从 <properties> 元素
            或者下面 <filters>中指定的 properties 文件中读取变量的值
            替换 ${变量名} 
            -->
            <filtering>true</filtering>
        </resource>
    </resources>
    <filters>
        <filter>src/main/resources/my.properties</filter>
    </filters>
</build>

You can use <excludes> exclude specific files in the specified directory, support wildcard matching, such as by *.txt exclude .txt file with the extension.

Open the filter function through <filtering>true</filtering> , and then you can read the value of the variable pom.xml file, <properties> element or <filters> ${variable name}.

have to be aware of is:

When there is the same variable name in the pom.xml file, <properties> element or <filters> , the priority of reading the variable is as follows:

<filters> > <properties> > pom.xml

Let's use an example to illustrate the above function. Define a hello.txt file. In the file, ${variable name} to verify the function of variable substitution. test.txt defined to verify the file exclusion function, and one is defined. my.properties file specifies the value of the variable, as shown in the figure below:

image.png

Use the following command to compile and package:

mvn clean package

The output result is as follows:

image.png

From the results, we can see that the test.txt file has been excluded, and the value of the custom variable has been replaced correctly.

Resource files are files to be used in Java code. When the code is executed, it will go to the specified directory to find these files. Under normal circumstances, the resource files we use (various xml, properties, xsd files, etc.) are placed under src/mian/resources . When using Maven to package, Maven can package these resource files into the corresponding jar package or war package by default middle.

But sometimes, you may put the resource file into src/main/java under, for example Mybatis of Mapper.xml file is and Mapper.java together, it led to a java jar file that can hit the bag, Mapper.xml has not reached the jar package . At this time, you need to add specific configuration in pom.xml to put these resource files into the jar package or war package.

Configuration There are two ways, one is in <build> add nodes under the label <resources> label node, the second is <build> under the label node <plugins> label node configuration maven-resources-plugin plug-ins and other processing resources file.

  • <resources> into the label manner src/main/java in properties and xml file
<build>
    .......
      <resources>
        <resource>
            <directory>src/main/resources</directory>
            <excludes>
                <exclude>**/*.properties</exclude>
                <exclude>**/*.xml</exclude>
             </excludes>
            <filtering>false</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
    ......
</build>
  • maven-resources-plugin the introduction of plug-ins src/main/java in properties and xml file
<plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.5</version>
    <executions>
        <execution>
            <id>copy-xmls</id>
            <phase>process-sources</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>                                  
                <outputDirectory>${basedir}/target/classes</outputDirectory>
                <resources>
                    <resource>
                        <directory>${basedir}/src/main/java</directory>
                        <includes>
                            <include>**/*.xml</include>
                        </includes>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

Reference documents

maven guide


惜鸟
328 声望2.3k 粉丝