Introduction to the

Excellent build tool

On a daily basis, if you need to compile, run unit tests, generate documentation, package, and deploy more than just writing source code, this process is a build. It would be too expensive to do it manually. Maven abstracts out the build lifecycle model and uses plug-ins to accomplish our task

Strong dependency management

If your Java program depends on many libraries, you need to reference them in your project. As dependencies grow, versioning inconsistencies, versioning conflicts, and dependency bloat follow. Maven provides an excellent solution for locating an artifact through a coordinate system. That is, Maven can find a Java class library (such as a JAR file) through a set of coordinates. Maven provides a free central repository for almost any popular open source library

Coordinates and dependencies

Maven definition rule: Any component can be uniquely identified with Maven coordinates, including groupId, artifactId, Version, Packaging, and Classifer. Coordinates are used to locate an artifact in the Maven repository. The component file name corresponds to the coordinate, and the general rule is artifacTID-version [-classifier]. Packaging.

coordinates

1. GroupId: Defines the actual project to which the current Maven project belongs

A real project is not one-to-one with a Maven project, and a real project may contain multiple Maven projects. A real project is not defined to a company name, but to a project name under the companyCopy the code

2. ArtifactId: Defines a Maven project within the actual project

3. Version: Defines all current versions of the Maven project

4. Packaging: Define how Maven projects are packaged

5. Classifier: Define some subordinate members of the component output

Jar, app-2.0.0-javadoc.jar, app-2.0.0-source.jar cannot be defined directly. The dependencies need to be generated with the help of plug-insCopy the code

Depend on the configuration

<dependency> <groupId>... </groupId> <artifactId>... </artifactId> <version>... </version> <type>... </type> -- Packaging for project coordinates, default jar <scope>... </scope> -- dependency scope <optional>... </optional> -- Exclusions -- Transitive dependencies <exclusion>... </exclusion> </exclusions> </dependency>Copy the code

Depend on the range

An important concept: Maven uses a classpath when compiling the main project code; Another set of Classpath is used when compiling and executing the test code; Use a clasSPATH when you actually run the project

The dependency scope is used to control the dependency relationship to the three classpath types (compile CLASspath, test classpath, and run classpath), as shown below, with Y indicating valid and – indicating invalid

Transitive dependence

If A depends on B, and B depends on C, then B is A direct dependence of A, that’s the first direct dependence, C is A direct dependence of B, that’s the second direct dependence, and C is A transitive dependence of A. The scope of the first direct dependence and the scope of the second direct dependence determine the scope of transitive dependence.

If the second direct dependency declaration is an optional dependency, it is not transitive

Rely on mediation

First rule: The shortest way is first

If project A has dependencies A->B->C->X(1.0),A->D->X(2.0), where X is A transitive dependency of A, but there are two versions of X on both dependency paths, which X will be introduced? According to the first principle, X(2.0) is introduced

Second rule: the first declaration takes precedence

If project A has dependencies A->B->X(1.0),A->C->X(2.0), where X is A transitive dependency of A, but there are two versions of X on both dependency paths, which X will be introduced? According to the first principle, it is no longer distinguishable, so we need to introduce X(1.0) declared first according to the second principle.

Eliminate dependence on

Transitive dependencies implicitly introduce many dependencies into the project, greatly simplifying the management of project dependencies, but in some cases can also cause problems, so dependencies need to be excluded. Where do dependencies need to be removed?

Case 1: A->B->C, but C is A snapshot version, which will directly affect the current project A due to instability. It is often necessary to exclude C when A introduces B, while explicitly referencing stable versions of C in A project

Case 2: A->E->F, but F may not be available in the central repository due to copyright issues, etc. There is an alternative implementation H at that time. Then it is possible to exclude F when A introduces E, while explicitly referring to H in A project

Consider this: if you don’t rule out introducing the C-stable version or H directly into A, is it possible to resolve by yourself according to the dependency mediation principle?

Check the rely on

When dependencies are parsed by Maven, they form a dependency tree, and the following command makes it clear that a dependency was introduced through that transfer path

mvn dependency:tree

Dependencies can be analyzed by using the following command. There are two important parts of the analysis result. One is that a dependency is not explicitly declared but is used, and the risk is that the dependency is upgraded and transitive dependencies are upgraded. One section is explicitly declared but not used. This section shows the dependencies needed to compile the main code and test code. The dependencies needed to execute the tests and run time are not found by the command, such as spring-core

mvn dependency:analye

warehouse

layout

Each component has a unique coordinate that defines its unique storage path in the repository. This is how Maven’s repository is laid out. Maven repositories are stored based on a simple file system.

classification

Maven repositories are divided into local and remote repositories.

When Maven searches for components based on coordinates, it first looks at the local repository and uses the component directly if it exists in the local repository. If the component does not exist in the local repository, or if a newer version of the component is needed, Maven will go to the remote repository, send the required component, and download it to the local repository for further use. Maven will report an error if neither the local repository nor the remote repository has the required artifacts.

Local repository

XML file. If not specified, ~/.m2/repository is default

<! -- localRepository | The path to the local repository maven will use to store artifacts. | | Default: ${user.home}/.m2/repository <localRepository>/path/to/local/repo</localRepository> --> <localRepository>F:/repository</localRepository>Copy the code

Remote warehouse

  • The central warehouse

Maven comes with a remote warehouse, can open $M2_HOME/lib/Maven – model – builder – 3.0. The jar and access org/apache/Maven/model/pom – 4.0.0. XML view, this file is also a super pom, All Maven projects inherit the Super POM

<repositories>
    <repository>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>
Copy the code
  • Private servers

A warehouse service set up on a LAN, acting as a remote warehouse on a wan

When Maven needs to download the first component, it requests it from the private server. If the component does not exist on the private server, it downloads it from an external remote repository, caches it on the private server, and then services Maven’s download request. Some components (custom components) that cannot be downloaded from external repositories can also be uploaded locally to private servers for everyone to use

  • Other warehouse

Such as Ali Maven repository

Configuring the Remote Repository

In some cases, Maven’s default central repository does not meet requirements, the artifacts are in other remote repositories, or you do not want to use the default remote repository (for reasons such as slow download), you can override Maven’s central repository and configure other remote repositories. The configuration is as follows:

<repository> <id>ali</ ID > Central overrides the central Repository< name>Ali Repository</name> -- Repository name <url>https://maven.aliyun.com</url> -- Repository address < Layout >default</ Layout > -- Warehouse layout < Releases > -- Setting the stable version policy <enabled> True </ Enabled > -- supports downloading stable versions <updatePolicy>daliy</updatePolicy> -- Configure how often Maven checks for updates from the remote repository, default daliy. Never c. Interval :X Indicates that the check is performed every X minutes. Daliy says Maven checks once a day; Always indicates that every build checks the update <checksumPolicy> Ignore </checksumPolicy> -- configures maven to check the policy for checksum file checksum failures, default warn. Ignore: Fails to ignore the checksum during construction. Warn indicates that alarms are generated during construction. Fail means to fail the build </releases> <snapshots> </snapshots> </repository> </repositories>Copy the code

Configuring Warehouse Authentication

For security reasons, it is common to add authentication information (such as account numbers and passwords) to the repository. Remote repository can be configured in POM or setting file, but warehouse authentication can only be configured with setting, which is also for security reasons (POM shared, setting generally only on the local machine).

< Servers > <server> <id>ali</id> <username>admin</username> <password> Admin123 </password> </server> </ Servers >Copy the code

Deploy to a remote repository

One function of private server is to deploy third-party components or self-written components. How to deploy components to private server repository? You can log in the corresponding warehouse to manually upload components; You can also configure the POM file and Maven’s deploy command to deploy artifacts to a remote repository as follows (see the previous section for authentication)

<distributionManagement> <snapshotRepository> Depends on the specified warehouse can also support a snapshot version < id > snapshots < / id > - custom < name > snapshots warehouse < / name > - the name of the warehouse The < url > http://xx.com.cn/content/repositories/snapshots < / url > - warehouse address < / snapshotRepository > < repository > - release stable version, <id>thirdparty</id> <name> Thirdparty </name> <url>http://xx.com.cn/content/repositories/thirdparty</url> </repository> </distributionManagement>Copy the code

The mirror

If warehouse X can supply everything stored in warehouse Y, then X is a mirror image of Y. Maven.net.cn/content/gro… Maven is a mirror of the central repository repol.maven.org/maven2 in China. Due to location, this mirror can provide faster service than the central repository, so you can configure Maven to use these two mirrors instead of the central repository. The image can only be configured in the setting file.

<mirrors> <id>nexus-aliyun</id> <mirrorOf> Central </mirrorOf> Can * said all warehouse < name > Nexus aliyun < / name > - mirror name < url > http://maven.aliyun.com/nexus/content/groups/public < / url > - mirror address </mirror> </mirrors>Copy the code

If authentication information is required, configure authentication information based on the ID.

The mechanism for relying on parsing from the repository

How does Maven parse and use dependencies from the repository?

  • Resolve artifacts directly from the local file system when the dependency scope is system
  • After calculating the warehouse path according to the dependent coordinates, try to find the component directly from the local warehouse. If the corresponding component is found, the parsing succeeds
  • When no such component exists in the local repository, if the dependent version is an explicit release component, such as 1.2, then all remote repositories are traversed, found, downloaded and used
  • If the dependent component is RELEASE or LATEST, the groupId/artifactId/maven-metadata. XML of all remote repositories is read based on the update policy, and the real value of RELEASE or LATEST is calculated by merging it with the corresponding metadata of the local repository. Then check local and remote repositories based on this value, as in steps 2 and 3
  • If rely on the component is the SNAPSHOT, is based on update strategy reads all remote warehouse metadata groupId/artifactId/version/maven – metadata. XML, corresponding with the local warehouse metadata combined to calculate the SNAPSHOT real value, Then check local and remote repositories based on this value, as in steps 2 and 3
  • If the last resolved version is a SNAPSHOT with a timestamp, copy the timestamp file (for example, redis-core-1.0.5-20210223.073400-7.jar) to a non-timestamp file (redis-core-1.0.5-snapshot.jar). And use artifacts in a non-timestamp format

Life cycle and plug-ins

Maven’s life cycle is an abstraction and unification of the build process, including cleanup, compilation, testing, packaging, deployment, site, and almost all of the build steps. Maven’s life cycle is not implemented; specific functions are implemented through plug-ins.

Three life cycles

Defines the phases that each lifecycle contains, and the post-execution phase executes the previous phases of the same lifecycle, but does not affect other lifecycles

Clean Life cycle

Pre-clean -- Work that needs to be done before cleanup Clean -- Clean files generated during the last build post-clean -- work that needs to be done after cleanupCopy the code

Default Life Cycle

Process-resource -- copy the contents of the SRC /main/resources directory to the main classpath directory of the project output after variable substitution etc... Compile -- Compile the contents of the SRC /main/ Java directory and print them to the main classpath directory... Process-test-resource -- copy the contents of the SRC /main/resources directory to the classpath directory of the project output... Test-compile -- compile the contents of the SRC /test/ Java directory and print them to the main classpath directory... Test - Run tests using a test framework, the test code is not packaged... Package - Packages compiled code into published formats such as JAR, WAR... Verify install -- installs packages into local repositories for other Maven projects to use deploy -- copies packages to remote repositories for other developers and Maven projects to useCopy the code

Sit Life cycle

pre-sit
sit
post-sit
sit-deploy
Copy the code

Call life cycle

Maven can invoke the lifecycle from the command line, for example

mvn clean
mvn package
mvn sit
mvn clean install
mvn clean install sit
Copy the code

Plug-in binding

Plug-in goals

Plug-ins are usually not monolithic, providing many functions, each with a purpose. For example, The Maven-dependency plugin has targets such as Dependency: Tree and denpendency: Analyze, preceded by a colon and followed by a target

Plug-in binding

Phases of the Maven lifecycle are tied to the goals of the plug-in to accomplish a specific task. Such as

  • Built-in binding

Maven binds a number of plug-in goals to major lifecycle phases. As shown below, the plug-in used in the default life cycle is related to the packaging type. The following default is the use of plug-in packaged as jar type

  • Custom binding

In addition to built-in bindings, you can also define the option to bind a target to a phase of the lifecycle, allowing you to perform more distinctive tasks during the build process. Common customisations include generating source jar packages, as shown below, to bind maven-source-plugin:jar-no-fork targets to the compile phase of the default lifecycle

<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>3.0.0</version> <executions> <phase>compile</phase <goal>jar-no </goal> </executions> </executions> </executions> </plugins> </build>Copy the code

If you just declare plug-ins

<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> The < version > 3.0.0 < / version > < / plugin > < / plugins > < / build >Copy the code

Execute MVN Verify to find that the jar-no-fork target is also executed. This is because the target of the plug-in already defines the default binding life cycle phase, and if the plug-in is declared the corresponding target will be executed when the life cycle is executed. How do I check if the target of a plug-in is bound to a lifecycle phase by default?

MVN help: go - Dplugin = groupId: artifactId: version - Dgoal = goal - Ddetail groupId: artifactId: version can be used to target alternative - Dgoal = prefix Specifies the plug-in target to view. -ddetail Displays an example of detailed informationCopy the code

If at the same stage of the life cycle, the plug-in target declared first is executed first; When a plug-in target is bound to different lifecycle phases, the execution order is determined by the sequence of lifecycle phases

Plug-in resolution mechanism

Aggregation and inheritance

The aggregation

The aggregation module knows which modules are aggregated; the aggregation module does not know the aggregation module

Maven parses the CHECKsum module’s POM, analyzes the built modules, calculates a reactor build order, and then builds each module in turn based on that order.

Aggregation modules have two directory structures

The reactor

A build structure made up of all modules. For a single module project, the reactor is the module itself. In the case of a multi-module project, the reactor contains a relationship of inheritance and aggregation between modules.

  • Account-aggregator aggregates the following modules

  • The reactor

Build order

The construction sequence of the polymerization project is calculated according to the reactor. Maven reads the POM sequentially and builds the module if the POM has no dependencies, otherwise builds its dependencies first, and builds dependencies first if the dependencies also depend on other modules.

  • The above reactor construction sequence

inheritance

The child module knows which parent module is inherited from, and the parent module does not know which child modules are inherited from

All modules inherit super POM by default.

The POM of the child module needs to specify the relative position of the ordinary parent POM.

There are many POM elements in the parent POM that can be inherited.

Dependency management

Maven provides a dependencyManagement element that allows child modules to inherit the dependency configuration of their parent modules while ensuring flexibility in the use of child module dependencies. The dependency declaration in this element does not introduce the actual dependencies, but it does constrain the use of dependencies under Dependencies. The child module references the parent module dependencyManagement declaration by specifying groupId and artifactId

Plug-in management

Maven provides the pluginManagement element to manage plug-in dependencies. GroupId and artifactId are specified only when the plugin sound for this element is declared in the submodule

DependencyManagement and pluginManagement elements unify versions of dependencies within the scope of the project

Flexible build

Maven has three built-in features, attributes, profiles, and resource filtering, to support build flexibility.

Maven properties

Built-in attributes: There are two common built-in attributes. Basedir represents the project root directory, which contains the pom.xml file. {basedir} represents the project root directory, which contains the pom.xml file; Basedir represents the project root directory, which contains the pom.xml file; {version} indicates the project version

Custom attributes: Attributes defined in the POM

< the properties > < encoding > utf-8 < / encoding > < spring - version > 3.2.2. RELEASE < / spring - version > < spring integration - version > 2.2.2. RELEASE < / spring integration - version > < / properties >Copy the code

POM attribute: Refers to the value of the corresponding element in the POM file. For example, ${project.artifactid} corresponds to the value of the element, and others are similar

Settings attribute: As with the POM attribute, starting with Settings refers to the value of the XML element in the settings. XML file. For example, ${settings.localRepository} gets the address of the localRepository

Environment variables: All environment variables can be referenced starting with env. For example, ${env.javA_HOME} gets the value of the JAVA_HOME environment variable

Java System Properties

Maven Profile

Define the profile

<profiles> <profile> < ID >dev</ ID > -- PROFILE ID <activation> <activeByDefault>true</activeByDefault> -- Default activation </activation> <properties> -- Custom properties <maven.log-level>DEBUG</maven.log-level> <maven.sql-log-level>DEBUG</maven.sql-log-level> <maven.console-log-enable>true</maven.console-log-enable> </properties> </profile> <profile> <id>uat</id> <properties> <maven.log-level>INFO</maven.log-level> <maven.sql-log-level>INFO</maven.sql-log-level> <maven.console-log-enable>false</maven.console-log-enable> </properties> </profile> </profiles>Copy the code

To activate the profile

  • The -p parameter plus the PROFILE ID
mvn clean package -Puat
Copy the code
  • The default activation
<activation> <activeByDefault>true</activeByDefault> -- Default activation </activation>Copy the code

Resource filters

Maven properties are resolved by default only in POM. Maven attributes in SRC /main/resources files cannot be resolved by default.

The maven-resources-plugin replaces the maven attributes of files in the SRC /main/resources directory with resources filtering enabled

<build> <resources> <resource> <directory> SRC /main/resources</directory> <filtering> <build> <resources> <resource> <directory> SRC /test/resources</directory> <filtering>true</filtering> </resource> </resources> </build>Copy the code

The following configuration

Get the env values, such as uat, then the filter-uat.properties properties and other Maven properties, and finally replace the SRC /main/resources properties

<build>
   <filters>
       <filter>src/main/resources/META-INF/filters/filter-${env}.properties</filter>
   </filters>
   <resources>
       <resource>
           <directory>src/main/resources</directory>
           <filtering>true</filtering>
       </resource>
   </resources>
</build>
Copy the code