The word Maven can be translated to mean expert. It is open source organized by Apache and mainly serves the construction, dependency management and project information management of Java platform projects.

With Maven, you can automatically compile, test, package, publish a project by writing some configuration and running a command.

The installation

Maven depends on the Java environment, so first make sure you have Java installed, first go to the official website to download Maven, then unzip it to any folder, and set the path to the M2_HOME environment variable. Add %M2_HOME%\bin (Windows) to PATH. For Linux, export PATH=$PATH:$M2_HOME/bin.

mvn -v # Run this command from the command line to view the Maven version
Copy the code

Repeat the process for upgrades.

The Maven configuration settings. XML is stored in the Maven installation directory conf file. It is global and can be copied to ~/.m2. The Settings. Maven’s dependencies are stored in the ~/.m2 folder in the repository folder.

Because Maven actually executes Java commands, we can set its parameters using the MAVEN_OPT environment variable. It is usually necessary to set its value to -xMS128m -XMx512m because it is possible to run out of memory for larger projects.

For Maven in the editor, we can set it to use the Maven we downloaded, so that we can avoid the inconsistent build behavior caused by the inconsistency of two Maven versions.

An introduction to

For Maven Project, the core is pom. XML (Project Object Model) where we need to write the Project build configuration information.

<?xml version="1.0" encoding="UTF-8"? >
<project 
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.demo</groupId>
    <artifactId>hello-world</artifactId>
    <version>0.0.1 - the SNAPSHOT</version>
    <name>hello world project</name>
    <description>Demo project</description>
</project>
Copy the code

The first line is the XML header, specifying the XML version and file encoding.

Then there is the project element, which is the root element of the configuration file and also declares the namespace of the POM.

Then there is modelVersion which can only be 4.0.0 for Maven2 and Maven3.

GroupId, artifactId, and Version define the basic coordinates of a project.

GroupId defines which group the project belongs to. It is usually named the same as the package name in Java. For example, if company A starts a myApp project, its groupId might be com.a.myapp.

ArtifactId defines the unique ID of the current Maven project in the group, since a project may have multiple subprojects or modules.

Version specifies the version of the current project. SNAPSHOT indicates the SNAPSHOT version.

Name gives the project a friendlier name, and description is the description of the project.

These fields define the basic information of the project, and now we can write the project code.

package com.demo.helloworld;

public class HelloWorld {
    public String sayHello(a) {
        return "hello world";
    }

    public static void main(String[] args) { System.out.println(sayHello()); }}Copy the code

Maven uses convention over configuration. In most cases, the project source code should be placed in the project folder SRC /main/ Java (Maven automatically searches for the source code in this directory), and the resources should be placed under SRC /main/ Resources. The test code is placed under SRC /test/ Java.

Our package name should also match groupId and artifactId.

Then perform

mvn clean compile
Copy the code

Clean is for Maven to clean the project output target directory. The compile task is used to compile projects into the target/classes directory.

We then write unit tests in JUnit, first adding JUnit’s dependencies to POM.xml.

<?xml version="1.0" encoding="UTF-8"? >
<project 
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
>

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.demo</groupId>
    <artifactId>hello-world</artifactId>
    <version>0.0.1 - the SNAPSHOT</version>
    <name>hello world project</name>
    <description>Demo project</description>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

</project>
Copy the code

To import a dependency, we need to fill in its base coordinates. With these coordinates, Maven will automatically download from the central repository. This dependency will be stored in the ~/.m2/repository folder.

Scope test indicates that dependencies are only valid for tests. Introducing junit into the main code will cause an error.

package com.demo.helloworld;

import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class HelloWorldTest {
    @Test
    public void test(a) {
        HelloWorld helloWorld = new HelloWorld();
        assertEquals("hello world", helloWorld.sayHello()); }}Copy the code

Then we need to do some configuration for Maven’s compiled plug-in, as it only supports Java 1.5 by default so we need to configure it for a later version of Java

<?xml version="1.0" encoding="UTF-8"? >
<project 
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
>

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.demo</groupId>
    <artifactId>hello-world</artifactId>
    <version>0.0.1 - the SNAPSHOT</version>
    <name>hello world project</name>
    <description>Demo project</description>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
        <! -- Configure source code -->
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <! -- Configure Java version -->
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>
Copy the code

Then perform

mvn clean test
Copy the code

It compiles the test file, runs the test, and finally sees the output of the test passing.

The next step is to package the project, and since we didn’t specify a package type for the project, the default is jar.

mvn clean package
Copy the code

Maven will automatically compile and test for us before we package it. If we pass it, we will put it into a jar package and put it in the target directory. The name is hello-world-0.0.1-snapshot.jar and it is named after artifactId and Version and the package type.

Test will automatically help us to compile, package will automatically help us to execute test, install will automatically help us to execute package, install is to install the project into the repository.

We can also use the archetype plugin to generate the skeleton of the project by running the MVN archetype:generate command, or create a New Maven project using the editor to select the project template.

coordinates

Maven finds a dependency by coordinates, and a set of coordinates is defined by elements.

  • groupIdA practical project of an organization
  • artifactIdA Maven project or module in an actual project
  • versionversion
  • packagingPacking methods:jar.war
  • classifierAncillary builds that define the build output are as followsHello - the world - 1.0.0 - javadoc. JarWhich contains Java documents,javadocIt’s just an accessory buildclassifier.

The first three must be defined. The packaging jar is the default jar, and the classifier cannot be defined directly.

Rely on

A project dependency needs to be placed in dependencies, and dependency has several child elements.

  • groupId.artifactIdversionIs the basic project coordinates.
  • typeDependency type, default isjar
  • scopeDepend on the range
  • optionalWhether or not an optional
  • exclusionsUsed to exclude transitive dependencies

The dependency range has several values to choose from. The scope of dependencies mainly controls the compile, test, and run classpath

  • compileBy default, it works at compile, test, and run
  • testIt only works with the test classpath, such as junit, as long as it is available at test time.
  • providedFor compilation and testing, for exampleservlet-apiBecause the runtime container provides it, there is no need to introduce it again.
  • runtimeRuntime dependencies, which are valid for testing and runtime but not compile-time, such as JDBC driver implementations, only require specific driver implementations when they need to be run.
  • systemThe system depends on the scope, which is associated withprovidedThe dependency scope is exactly the same, except that its dependencies must be usedsystemPathExplicitly specify dependency paths, which are not resolved through Maven repositories.
    <dependencies>
        <dependency>
            <groupId>javax.sql</groupId>
            <artifactId>jdbc-stdext</artifactId>
            <version>2.0</version>
            <scope>system</scope>
            <systemPath>${java.home}/lib/rt.jar</systemPath>
        </dependency>
    </dependencies>
Copy the code

Another type of import is the import dependency scope, which does not affect the above three dependency scopes.

Transitive dependence

Passing dependencies means that if we rely on spring-core (compile) but spring-core relies on commons-logging (compile), then our project also relies on commons-logging (compile). With this mechanism, we don’t have to worry about what Spring depends on, and instead of manually installing its dependencies, Maven automatically introduces the necessary indirect dependencies into the current project. The starting dependency for Spring Boot is to leverage Maven’s transitive dependency.

Dependency scope also has an impact on transitive dependencies.

The left represents direct dependencies, the top represents indirect dependencies, and the middle represents transitive dependencies.

Rely on mediation

For example, if there are two dependencies in our project that are the same but have different versions, Then Maven will see who has the shortest path, and the shortest path will take precedence.

If they are the same length, Maven looks at the dependency declarations in the POM and takes precedence over whoever comes first.

Optional dependence

If our project depends on A (compile), A depends on B (compile) and C (compile), but B and C are defined as optional, then the dependency will not be passed. Dependency optional can be specified by
true
.

Eliminate dependence on

If we want to exclude a transitive dependency, such as Jackson, which spring Boot uses by default, and if we want to use Gson, then we can exclude jackason and explicitly introduce Gson.

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-json</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.5</version>
    </dependency>
</dependencies>
Copy the code

Merge dependent

If we rely on many modules of a project and have the same version number because it is a project, we will have to fill in the same version number for each dependency and then change it one by one for the upgrade.

At this point we can declare a variable and use it elsewhere.

<?xml version="1.0" encoding="UTF-8"? >
<project 
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
>

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.demo</groupId>
    <artifactId>hello-world</artifactId>
    <version>0.0.1 - the SNAPSHOT</version>
    <name>hello world project</name>
    <description>Demo project</description>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spring.version>2.5.6</spring.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <! --... >
    </dependencies>

</project>
Copy the code

${} can introduce Maven attributes.

warehouse

The output of any project or plug-in in Maven is called a artifact. Any component will have a unique coordinate. Maven’s dependencies are centralized in a repository for reuse, rather than each project having a Lib-like folder to hold its dependencies.

Maven’s repository is divided into remote repository and local repository. Maven first searches for dependencies in the local repository through coordinates. If there are no dependencies, Maven downloads them from the remote repository and then uses them in the local repository. If none is present, an error is reported.

You can customize remote repositories. Maven comes with a remote repository that contains most of the artifacts. By default, you go to this central repository to download the artifacts.

Private server is another kind of remote warehouse, in order to save broadband and time, in the LAN to build a private warehouse, with its proxy external remote warehouse, internal projects can also be installed on the private server for other projects.

In addition to the two above, there are other open remote repositories. Such as JBoss Repository.

Local repository

The default location of the local repository is the.m2/repository folder in the current user directory. If we want to change its location we can modify the.m2/settings.xml file.

<settings>

    <localRepository>D:\maven\repository</localRepository>

</settings>
Copy the code

If we have two local projects A and B, and project B depends on PROJECT A, we can install project A into the local repository so that we can rely on project A in project B. We can execute MVN clean install in project A to install project A into the local repository.

Remote warehouse

Maven needs to know at least one remote repository so that Maven can download artifacts locally. The central repository is the default remote repository, and all Maven projects pom.xml inherit a super POM, It is located in the Maven installation directory in the lib/ maven-model-Build-3.6.1.jar \org\apache\ Maven \model\ folder named POM-4.0.0.xml.

<?xml version="1.0" encoding="UTF-8"? >
<project>
    <modelVersion>4.0.0</modelVersion>

    <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>

    <pluginRepositories>
        <pluginRepository>
            <id>central</id>
            <name>Central Repository</name>
            <url>https://repo.maven.apache.org/maven2</url>
            <layout>default</layout>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <releases>
                <updatePolicy>never</updatePolicy>
            </releases>
        </pluginRepository>
    </pluginRepositories>

    <! --... >
</project>
Copy the code

Private servers

Private server is a special remote repository, it represents multiple external remote repositories, we use private server to download components, if not on the private server will fetch the remote download, and then cache.

configuration

If the artifacts we need are not in the central repository but in another repository, we can configure that repository in pom.xml.

<repositories>
    <repository>
        <id>jboss</id>
        <name>JBoss Repository</name>
        <url>http://repository.jboss.org/maven2/</url>
        <layout>default</layout>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>
Copy the code

The id must be unique. If you have a repository declaration with the same id as the central repository, it will be overwritten. The URL is the repository address, and releases releases and snapshots are used to control the download of releases and releases. False: disables the download.

Snapshot version is said version in the development, the change of the developing project will be ordinary, for example, we develop a project in a module, but it depends on another module, we will install it to the local dependence, so that you can use in our project, but if depend on the project has changed, but we will still use the cache module, local Maven checks each snapshot version to see if it is up to date and downloads the latest code if it is not.

Snapshots enable you to set the update frequency of Maven checks.

<snapshots>
    <updatePolicy>daily</updatePolicy>
    <checksumPolicy>ignore</checksumPolicy>
</snapshots>
Copy the code

Never, always Components are checked every time, daily daily (default).

Maven checksumPolicy is a warn warning that a component will be verified when it is downloaded by Maven.

Remote warehouse validation

For internal repositories that require authentication to run access, you can set the account and password for the repository in settings.xml.

<servers>
    <id>repo</id>
    <username>username</username>
    <password>password</password>
</servers>
Copy the code

Where ID corresponds to the remote warehouse ID defined by us.

Deploy to a remote repository

One of the functions of private servers is to deploy third-party components, and Maven can help us deploy components into the repository.

<project> <distributionManagement> <repository> <id>id</id> <name>Release Repository</name> The < url > http://196.0.0.1/path/to/release < / url > < / repository > < snapshotRepository > < id > snapshot < / id > < name > snapshot The Repository < / name > < url > http://196.0.0.2/path/to/release < / url > < / snapshotRepository > < / distributionManagement > < / project >Copy the code

Repository represents the repository of the release, snapshotRepository represents the repository of the snapshot, and ID is the unique identifier through which we can set accounts and passwords.

Then we can run the following command to publish

mvn clean deploy
Copy the code

The repository resolves dependency mechanisms

Maven goes back to look locally when the dependency return is System.

When it comes to explicit builds such as 1.2, 1.3-beta-1, Maven will go to all remote repositories and download them locally.

When the dependent version is RELEASE LATEST and SNAPSHOT, the component metadata will be searched for in all remote repositories according to the update policy, and then merged with the local metadata, and the version will be found by the merged value.

The mirror

We can also set up the image server in settings.xml.

<mirrors>
    <mirror>
        <id>maven.net.cn</id>
        <name> maven central mirror</name>
        <url>http://maven.net.cn/content/groups/public/</url>
        <mirrorOf>central</mirrorOf>
    </mirror>
</mirrors>
Copy the code

We set a mirror for the central repository above. We can also set mirrorOf to * to match all remote repositories.

Life cycle and plug-ins

Maven has three life cycles: Clean, Default, and Site. Maven’s life cycle is an abstract existence, like an interface, that hands off the real work to a plug-in. These three life cycles are independent of each other.

Each lifecycle has phases. For example, the clean lifecycle has three phases, pre-clean, Clean, and post-clean. The phases are sequential, and when the clean phase is executed, the pre-clean before it is executed.

There are phases of the Clean lifecycle

  1. pre-cleanPerform the work that needs to be performed before the cleanup
  2. cleanClean up last component
  3. post-cleanOperations to be performed after clearing

The default life cycle is the most core part, which has the following stages

  1. validate
  2. initialize
  3. generate-sources
  4. process-sourcesHandles the main resource file, generallysrc/main/resourcesFiles in the directory.
  5. generate-resources
  6. process-resources
  7. compileCompile the project source code.
  8. process-classes
  9. generate-test-sources
  10. process-test-sourcesProcess project test resource files.
  11. generate-test-resources
  12. process-test-resources
  13. test-compileCompile test source
  14. process-test-classes
  15. testRun tests using the unit testing framework.
  16. prepare-package
  17. packageTake the compiled code and package it into a releasable format.
  18. pre-integration-test
  19. integration-test
  20. post-integration-test
  21. verify
  22. installInstall packages into Maven’s local repository for use by other local projects
  23. deployCopy packages to remote repositories.

The purpose of the site lifecycle is to create and publish a project site.

  1. pre-siteActions to perform before building the site
  2. siteGenerate project site documentation
  3. post-sitePerform the work to be done after building the site
  4. site-deployPublish the site to the server

The command line

The main way to perform Maven tasks is to invoke Maven’s life cycle phase.

MVN Clean is the clean phase that performs the clean lifecycle

MVN test is the test phase of the default life cycle

MVN Clean Install is the install phase that executes the Clean phase and default phase of the clean lifecycle.

Plug-in goals

Maven only defines the life cycle, but the actual work is left to the plug-in. A plugin will have one or more goals for each function, such as Surefire: Test surefire is the name of the plugin, test is the target of the plugin, and Surefire is the default test plug-in for Maven.

Phases of Maven’s life cycle are tied to the goals of the plug-in to accomplish real tasks.

Maven binds a number of plug-in targets by default to the main lifecycle phase, and the corresponding plug-in is executed when the lifecycle phase is called.

Custom binding

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>2.1.1</version>
            <executions>
                <execution>
                    <id>attach-sources</id>
                    <phase>verify</phase>
                    <goals>
                        <goal>jar-no-fork</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
Copy the code

Above we bound the Jar-no-fork target of the Maven-source-plugin to the Verify phase. Id is the task name.

The plug-in configuration

The plug-in also has parameters, which can be set either on the command line or in pom.xml.

MVN package-dmaven.test. skip=true -d is used to set Java system properties. Maven only reuses this parameter.

In POM.xml we can set parameters through configuration.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>
Copy the code

In addition to setting plug-in parameters in the outer layer (global), we can also set an execution parameter.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.3</version>
            <executions>
                <execution>
                    <id>ant-validate</id>
                    <phase>validate</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                    <configuration>
                        <tasks>
                            <echo>lalala</echo>
                        </tasks>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
Copy the code

Command line invoke plug-in

We can also invoke plug-in targets from the command line.

mvn [options] [goal<s>] [phase[s]]
Copy the code

Because some plug-in targets are not suitable for binding to lifecycle phase execution, we can execute the plug-in targets directly from the command line.

mvn dependency:tree # View project dependencies
# Of course we will write the groupId artifactId version of the plugin
Copy the code

We know that a plug-in has its basic coordinates. How does Maven find the corresponding plug-in via dependency?

Since dependency is the prefix of the Maven-dependency plugin, Maven can use the prefix to find the corresponding artifactId. Maven looks for plug-ins in the local repository, and if it doesn’t find them in the remote repository.

For plugins that do not specify a groupId, Maven defaults to org.apache.maven.plugins as its groupId. Maven sets the version of the core plug-in in the Super POM, which can be inherited in our project without setting it ourselves.

If a plug-in is neither a core plug-in nor a set version, all available versions of the repository are checked and a selection is made.

Aggregation and inheritance

Maven also supports multi-module development. We may have many modules in a project, and Maven can aggregate them together.

If we have a project app, it is divided into three modules A, B and C, namely three Maven projects, because they are one project, their groupId, version is the same.

Our project catalog might look something like this.

|-app
    |- a
        |- src
        |- pom.xml
    |- b
        |- src
        |- pom.xml
    |- c
        |- src
        |- pom.xml
    pom.xml
Copy the code

We have a pom.xml outermost layer that we use to aggregate modules in the project.

<?xml version="1.0" encoding="UTF-8"? >
<project 
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.demo.app</groupId>
    <artifactId>app-aggregator</artifactId>
    <version>1.0 the SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>a</module>
        <module>b</module>
        <module>c</module>
    </modules>
</project>
Copy the code

You need to set Packaging to POM, and then specify which modules it will aggregate.

The path in the module is relative to the module. If it is parallel to another module, the path is… / a, etc.

Instead of fetching components one by one, we now perform MVN Clean Install on the outermost layer. Maven parses pom.xml and calculates the order in which modules are built, and then executes them in that order.

inheritance

When we find that our submodules have a lot of the same configuration, we can use inheritance to eliminate duplication.

We can either create a parent pom.xml or we can reuse the aggregator pom.xml we created above without modifying it, but we need to modify the module that inherits it.

<! -- Module A -->

<?xml version="1.0" encoding="UTF-8"? >
<project 
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>app-a</artifactId>
    <parent>
        <groupId>com.demo.app</groupId>
        <artifactId>app-aggregator</artifactId>
        <version>1.0 the SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
</project>
Copy the code

We use parent to indicate which parent the module inherits from. The default value of the relativePath here is.. /pom.xml we can also omit it.

We now inherit the parent groupId and version, and can override it if we need a different value. Almost all projects can inherit from their parent.

If our parent declares a dependency, all child modules inherit the dependency, even if some modules don’t need it.

Maven provides dependencyManagement so that submodules do not introduce actual dependencies, only submodule declarations.

<dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot</artifactId>
        <version>2.1.7. RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-test</artifactId>
        <version>2.1.7. RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-test-autoconfigure</artifactId>
        <version>2.1.7. RELEASE</version>
      </dependency>
    </dependencies>
</dependencyManagement>
Copy the code
<! -- Module A -->
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot</artifactId>
  </dependency>
</dependencies>
Copy the code

With dependencyManagement, our submodule does not inherit directly, but there is no need to fill in the dependent version if it is declared to inherit.

Spring Boot takes advantage of Maven’s inheritance, and I’ll let you fill in the dependent versions ourselves.

There is also a pluginManagement (under the Build element) which acts the same as dependencyManagement, except that it applies to plug-ins.

test

Maven is tested using the Maven-Surefire-plugin.

-dskiptests, -dmaven.test. skip=true on the command line will skip not only tests but also compilation of the test code.

We can also run specified Tests, such as -dtest =*Tests to run only Tests at the end of Tests, * matching 0 or more characters. IT can also be used to split multiple parameters, such as -dtest =*Tests,*IT.

Maven properties

Maven POM.xml allows you to inject attributes using ${}, which supports six classes of attributes.

  • Built-in properties, such as${version}Project version and${basedir}Project root
  • POM property, which can be referencedpom.xmlAttributes, such as${project.version}.${project.build.sourceDirectory}
  • Custom properties, inpropertiesA custom property in
  • settings.xmlAttributes, such as${settings.loaclRepository}.
  • Java system properties, such as${user.name}
  • Environment variables, such as${JAVA_HOME}

Profile

The development and online environments on our projects often require different configurations. Profiles in Maven can be configured differently for different environments.

db.url=${db.url}
db.password=${db.password}
Copy the code
<profiles>
    <profile>
      <id>dev</id>
      <activation> 
        <activeByDefault>true</activeByDefault> <! -- Configure default activation -->
      </activation>
      <properties>
        <db.url>dev.url</db.url>
        <db.password>dev.password</db.password>
      </properties>
    </profile>
    <profile>
      <id>prod</id>
      <properties>
        <db.url>prod.url</db.url>
        <db.password>prod.password</db.password>
      </properties>
    </profile>
</profiles>

<! ${} from the properties file above can be injected into the properties property.
<build>
    <resources>
        <resource>
            <directory>${project.basedir}/src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
    <testResources>
        <testResource>
            <directory>${project.basedir}/src/test/resources</directory>
            <filtering>true</filtering>
        </testResource>
    </testResources>
</build>
Copy the code

We can then use -pdev on the command line to activate the development mode configuration. The configuration in profile is the configuration that takes effect when the current profile is activated.

frontend-maven-plugin

Sometimes we need to put the frontend and the back end together. We can use frontend-maven-plugin to install node NPM or yarn to execute the NPM script.

We just need to add this plug-in to the front-end module

  <plugin>
    <groupId>com.github.eirslett</groupId>
    <artifactId>frontend-maven-plugin</artifactId>
    <version>${frontend-maven-plugin.version}</version>
    <configuration>
      <installDirectory>target</installDirectory> <! -- Node installation directory -->
      <nodeVersion>v13.6.0</nodeVersion>
    </configuration>
    <executions>
      <execution>
        <id>install node and npm</id>
        <goals>
          <goal>install-node-and-npm</goal>
        </goals>
      </execution>
      <execution>
        <id>npm install</id>
        <goals>
          <goal>npm</goal>
        </goals>
        <configuration>
          <arguments>install</arguments>
        </configuration>
      </execution>
      <execution>
        <id>npm lint</id>
        <goals>
          <goal>npm</goal>
        </goals>
        <phase>compile</phase>
        <configuration>
          <arguments>run lint</arguments>
        </configuration>
      </execution>
      <execution>
        <id>npm run build</id>
        <goals>
          <goal>npm</goal>
        </goals>
        <phase>compile</phase>
        <configuration>
          <arguments>run build</arguments>
        </configuration>
      </execution>
      <execution>
        <id>npm run test</id>
        <goals>
          <goal>npm</goal>
        </goals>
        <phase>test</phase>
        <configuration>
          <arguments>run test</arguments>
        </configuration>
      </execution>
    </executions>
  </plugin>
Copy the code

It installs the new node and NPM itself, isolated from the global node. We then use its NPM goal to execute the NPM command. We can also use the Clean plug-in to clean up the generated code each time.

  <plugin>
    <artifactId>maven-clean-plugin</artifactId>
    <version>${maven-clean-plugin.version}</version>
    <executions>
      <execution>
        <id>remove existing output</id>
        <phase>compile</phase>
        <goals>
          <goal>clean</goal>
        </goals>
        <configuration>
          <excludeDefaultDirectories>true</excludeDefaultDirectories>
          <filesets>
            <fileset>
              <directory>build</directory>
            </fileset>
          </filesets>
        </configuration>
      </execution>
    </executions>
  </plugin>
Copy the code

dockerfile-maven-plugin

The Dockerfile-maven-plugin allows you to build and publish Docker images without having to manually enter commands.

  <plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <version>${dockerfile-maven-version}</version>
    <executions>
      <execution>
        <id>default</id>
        <goals>
          <goal>build</goal>
        </goals>
        <configuration>
          <contextDirectory>context</contextDirectory> <! -- Context directory defaults to current directory -->
          <dockerfile>not-context/Dockerfile</dockerfile> <! -- Dockerfile address, default is the current directory Dockerfile -->
          <buildArgs> <! Docker build command -->
            <IMAGE_VERSION>0.0.1</IMAGE_VERSION>
          </buildArgs>
        </configuration>
      </execution>
      <execution>
        <id>tag</id>
        <goals>
          <goal>tag</goal>
        </goals>
        <configuration>
          <repository>test/build-tag-version</repository> <! -- image name -->
          <tag>${project.version}</tag> <! -- Tag version -->
          <skip>true</skip> <! Set skip to true -->
        </configuration>
      </execution>
    </executions>
  </plugin>
Copy the code

We need a Dockerfile to build our image, which can be easily built using the Fat JAR method if it is a Spring Boot project.

FROM openjdk:8-jdk-alpine
VOLUME /tmp
COPY target/*.jar app.jar
ENTRYPOINT ["java"."-jar"."/app.jar"]
Copy the code

For more information about Spring Boot Docker, see Spring Boot Docker.