Getting started with Maven

table of Contents

Preface

Maven quick start

pom.xml preparation

Write the main code of the project

Write test code

Package and run

Maven coordinates and dependencies

Detailed coordinate

Dependent basic configuration

Summary of Maven commonly used commands


Preface

I have specially studied the basic knowledge of Maven before, but I did not record the meaning of many basic tags at that time. As a result, I can’t remember the meaning of many basic tags at all and I have nowhere to find it. I can only read the book again. It is very cumbersome and I do what I need Some simple introduction summary.

 

Maven quick start

pom.xml preparation

First create a maven project, and then we look at the core of maven, pom.xml. POM (Project Object Model, project object model) defines the basic information of the project, used to describe how the project is built, declare project dependencies, and so on. The following is the pom.xml of the hello-world project I just created:

<?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.qingcha.maven</groupId>
    <artifactId>hello-world</artifactId>
    <version>1.0-SNAPSHOT</version>


</project>

The first line of the code is the XML header, which specifies the version and encoding of the xml document. The project element is followed by the project element. The project is the root element of all pom.xml. It also declares some pom-related namespaces and xsd elements. Although these attributes are not required, the use of these attributes allows third-party tools (such as ide The xml editor in) helps us edit the pom quickly.

The first child element modelVersion under the root element specifies the version of the current pom model. For Maven 2 and Maven 3, it can only be 4.0.0.

The most important thing is the next three sub-elements groupId, artifactId, and version. They jointly define the basic coordinates of a project . In the world of Maven, any jar, pom or war is distinguished based on these basic coordinates. of.

The groupId defines which group the project belongs to . This group is often associated with the organization or company where the project is located. For example, if a project named myapp is created on googlecode, the groupId should be com.googlecode.myapp.

The artifactId defines the unique ID of the current Maven project in the group , and different subprojects (modules) in the group are often assigned different unique IDs.

version specifies the current version of the current project ---1.0-SNAPSHOT , SNAPSHOT means snapshot, indicating that the project is still under development and is an unstable version. As the project develops, the version will be continuously updated, such as upgrading to 1.0, 1.1-SNAPSHOT, 1.1, etc.

Write the main code of the project

The main code of the project is different from the test code. The main code will be packaged into the final component (such as jar), while the test code is only used when the test is running and will not be packaged. By default, Maven assumes that the main code of the project is located in the src/main/java directory. As long as the convention is followed, no additional configuration is required. Maven will automatically search this directory to find the main code of the project, so we need to follow the Maven convention and create it in this directory. Our own file: com/qingcha/maven/helloworld/HelloWorld.java, its content is as follows:

package com.qingcha.maven.helloworld;

public class HelloWorld {

    public String sayHello() {
        return "hello, world";
    }

    public static void main(String[] args) {
        System.out.println(new HelloWorld().sayHello());
    }
}

One thing to note here is that the package of Java classes in the project should be based on the groupId and artifactId of the project , which is clearer, more logical, and convenient to search for components or Java classes.

After the code is written, use maven to compile, run the command in the project root directory: mvn clean compile, and then you will see the console output the following information

[INFO] Scanning for projects...
[INFO] 
[INFO] -------------------< com.qingcha.maven:hello-world >--------------------
[INFO] Building hello-world 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ hello-world ---
[INFO] Deleting /project/Open-source/helloworld/target
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-world ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello-world ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /project/Open-source/helloworld/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.050 s
[INFO] Finished at: 2020-01-04T12:46:11+08:00
[INFO] ------------------------------------------------------------------------

From the output information, maven mainly does three operations:

  • clean task: use the clean plugin to delete the target/ directory first, by default all the output of the maven build is in the target/ directory
  • resources task: Since we have not defined project resources, skip it here
  • compile task: compile the main code of the project to the target/classes directory

Write test code

In order to make the project structure clear, the project main code and test code should be located in separate directories. The directory of the main code mentioned above is src/main/java, corresponding to Maven

The default test code directory in the project is src/test/java , so we also need to follow the convention to create our test classes in this directory. Of course, in order to test, you need to introduce dependencies first. Generally, the junit project is used in java. The dependencies are as follows

<?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.qingcha.maven</groupId>
    <artifactId>hello-world</artifactId>
    <version>1.0-SNAPSHOT</version>

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

</project>

The dependencies element is added to the above xml. This element can contain multiple dependency elements to declare the dependencies of the project. Here, the dependencies of junit are added. From the previous knowledge, we already know that groupId, artifactId, and version constitute the most basic of a Maven project. With this statement, Maven can automatically download junit-4.12.jar (download from Maven's central warehouse).

There is also a scope element behind, scope is the scope of dependency . If the scope of dependency is test, it means that the dependency is only valid for the test. In other words, using junit code in the test code is no problem, but using junit code in the main code will cause compilation errors. If you do not declare this element, the default scope is compile, which means that the dependency is valid for both the main code and the test code. Will be introduced in detail below

The next step is to create the test class. Under the mac version of idea, put the mouse under the name of the class to be created, and then press option+enter to quickly create the test class. The simple code of the test class is as follows:

package com.qingcha.maven.helloworld;

import org.junit.Assert;
import org.junit.Test;

public class HelloWorldTest {

    @Test
    public void sayHello() {
        HelloWorld helloWorld = new HelloWorld();
        Assert.assertEquals("hello, world", helloWorld.sayHello());
    }
}

Then we use Maven to execute the test, run mvn clean test, the output information is as follows:

[INFO] Scanning for projects...
[INFO] 
[INFO] -------------------< com.qingcha.maven:hello-world >--------------------
[INFO] Building hello-world 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ hello-world ---
[INFO] Deleting /project/Open-source/helloworld/target
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-world ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello-world ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /project/Open-source/helloworld/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello-world ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /project/Open-source/helloworld/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hello-world ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /project/Open-source/helloworld/target/test-classes
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello-world ---
[INFO] Surefire report directory: /project/Open-source/helloworld/target/surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.qingcha.maven.helloworld.HelloWorldTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.069 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.017 s
[INFO] Finished at: 2020-01-04T13:10:58+08:00
[INFO] ------------------------------------------------------------------------

The success at the bottom indicates that our test class has passed the execution. Analyzing the output information above, Maven has performed a total of six tasks:

  • clean task: use the clean plugin to delete the target/ directory first, by default all the output of the maven build is in the target/ directory
  • resources task: Since we have not defined project resources, skip it here
  • compile task: compile the main code of the project to the target/classes directory
  • testResources task: resources are not defined, skip
  • testCompile task: test code compilation
  • test task: execute the test

Package and run

After the project is compiled and tested, the next important step is to package. The current new project does not specify the packaging type. Use the default packaging type jar. Simply execute the command mvn clean package to package, and you can see the output

[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello-world ---
[INFO] Building jar: /project/Open-source/helloworld/target/hello-world-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.010 s
[INFO] Finished at: 2020-01-04T13:41:38+08:00
[INFO] ------------------------------------------------------------------------

Similarly, Maven will perform operations such as compilation and testing before packaging , and then execute the jar task at the end, that is, use the jar plug-in to generate a package named hello-world-1.0-SNAPSHOT.jar from the main project code, which is also located in / Under the target directory.

At this point, we have the output of the project. If necessary, we can copy this jar file to the classpath of other projects to use the HelloWorld class. But how can other Maven projects directly reference this jar? One more installation step is needed, execute mvn clean install:

[INFO] --- maven-install-plugin:2.4:install (default-install) @ hello-world ---
[INFO] Installing /project/Open-source/helloworld/target/hello-world-1.0-SNAPSHOT.jar to /Users/xujia/Downloads/mydocument/maven/maven-repository/com/qingcha/maven/hello-world/1.0-SNAPSHOT/hello-world-1.0-SNAPSHOT.jar
[INFO] Installing /project/Open-source/helloworld/pom.xml to /Users/xujia/Downloads/mydocument/maven/maven-repository/com/qingcha/maven/hello-world/1.0-SNAPSHOT/hello-world-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.009 s
[INFO] Finished at: 2020-01-04T13:48:19+08:00
[INFO] ------------------------------------------------------------------------

Similarly, when the installation command is executed, compilation, testing, and packaging tasks will be automatically executed . From the output information, you can see that the install task installs the jar package output by the project into the Maven local warehouse. You can open the corresponding folder to see the HelloWorld project. Pom and jar. When we talked about the downloading of pom and jar of junit, we said that only the components can be used by all Maven projects after they are downloaded to the local warehouse . Here is the same principle. Only after the components of HelloWorld are installed in the local warehouse, other Maven The project can use it.

The jar package generated by default packaging cannot be run directly, because the class information with the main method will not be added to the manifest (open the META-INF/MANIFEST.MF file in the jar file, you will not be able to see the Main-Class line ), in order to generate an executable jar file, we need to use the maven-shade-plugin plugin (there are many ways to generate an executable jar package, if you are interested, you can google it yourself), configure the plugin as follows:

<build>
                    <!-- 两种方式可以生成可执行jar包 -->
            <!--<plugin>-->
                <!--<groupId>org.apache.maven.plugins</groupId>-->
                <!--<artifactId>maven-shade-plugin</artifactId>-->
                <!--<version>3.2.1</version>-->
                <!--<executions>-->
                    <!--<execution>-->
                        <!--<phase>package</phase>-->
                        <!--<goals>-->
                            <!--<goal>shade</goal>-->
                        <!--</goals>-->
                        <!--<configuration>-->
                            <!--<transformers>-->
                                <!--<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">-->
                                    <!--<mainClass>com.qingcha.maven.helloworld.HelloWorld</mainClass>-->
                                <!--</transformer>-->
                            <!--</transformers>-->
                        <!--</configuration>-->
                    <!--</execution>-->
                <!--</executions>-->
            <!--</plugin>-->

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.qingcha.maven.helloworld.HelloWorld</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
    </build>

Now run mvn clean install again, you will see hello-world-1.0-SNAPSHOT.jar and original-hello-world-1.0-SNAPSHOT.jar in the /target directory, the former is runnable with Main-Class information jar, the latter is the original jar. Open the META-INF/MANIFEST.MF of hello-world-1.0-SNAPSHOT.jar, you can see that it contains the Main-Class information, and you can determine where the program entry is ( The command to decompress the jar package is: jar xvf hello-world-1.0-SNAPSHOT.jar)

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: xujia
Created-By: Apache Maven 3.5.4
Build-Jdk: 1.8.0_172
Main-Class: com.qingcha.maven.helloworld.HelloWorld

Finally run the jar package: java -jar hello-world-1.0-SNAPSHOT.jar, you can see the console output hello, world, perfect~

 

Maven coordinates and dependencies

Detailed coordinate

Maven coordinates introduce order for various components, each component must clearly define its own coordinates, and a group of Maven coordinates is defined by some elements, they are groupId, artifactId, version, packaging, classifier, first give a group The coordinates are defined as follows:

<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-indexer</artifactId>
<version>2.0.0</version>
<packaging>jar</packaging>

Let's explain each coordinate element in detail below

  • groupId : Define the actual project to which the current Maven project belongs. First of all, there is not necessarily a one-to-one relationship between the Maven project and the actual project. For example, the actual project of springframework has many Maven projects, such as spring-core, spring-context, etc. Therefore, an actual project is often divided into many modules, which is similar to the group concept we mentioned above. Secondly, the groupId should not correspond to the organization or company to which the project belongs, because there are many actual projects under an organization. If the groupId is only defined to the organization level, then the artifactId can only define the Maven project, then the actual project level will be difficult to define. Finally, the representation of groupId is similar to the representation of Java package names, usually in a one-to-one correspondence with the domain name. In the above example, the groupId is org.sonatype.nexus, org.sonatype represents a non-profit organization established by Sonatype, nexus identifies the actual project Nexus, and the groupId corresponds to the domain name nexus.sonatype.org.
  • artifactId : This element defines a Maven project (module) in the actual project. The recommended approach is to use the actual project name as the prefix of the artifactId, such as nexus-indexer in the above example.
  • version : This element defines the current version of the Maven project. For example, the version of nexus-indexer in the above example is 2.0.0.
  • packaging : This element defines how the Maven project is packaged. First, the packaging method usually corresponds to the file extension of the generated component. If the packaging is jar in the above example, the final file name is nexus-indexer-2.0.0.jar. For Maven projects that use war packaging, there will be a .war file in the final generated component, but this is not absolute. Secondly, the packaging method will affect the life cycle of the build. For example, jar packaging and war packaging will use different commands. Finally, when packaging is not defined, Maven will use the value jar
  • classifier : This element is used to help define some auxiliary components of the build output. The auxiliary component corresponds to the main component. For example, the main component in the above example is nexus-indexer-2.0.0.jar. The project may also generate nexus-indexer-2.0.0-javadoc.jar and nexus-indexer- by using some plug-ins. 2.0.0-sources.jar Some accessory components include java documentation and source code. At this time, javadoc and sources are the classifiers of these two accessory components. In this way, the accessory component also has its own unique coordinate. Note that you cannot directly define the classifier of the project, because the accessory components are not generated directly by the project by default, but are generated with the help of additional plug-ins.

Among the above five elements, groupId, artifactId, and version must be defined, packaging is optional (jar by default), and classifier cannot be defined directly.

Dependent basic configuration

A dependency declaration can contain the following elements:

<project>
    ...
    <dependencies>
        <dependency>
            <groupId>...</groupId>
            <artifactId>...</artifactId>
            <version>...</version>
            <type>...</type>
            <scope>...</scope>
            <optional>...</optional>
            <exclusions>
                ...
                <exclusion>
                    ...
                </exclusion>
            </exclusions>
        </dependency>
        ...
    </dependencies>
    ...
</project>

The dependencies under the root element project can contain one or more dependency elements to declare one or more project dependencies. The elements that each dependency can contain are:

1. groupId, artifactId and version: the basic coordinates of the dependency. For any dependency, the basic coordinates are the most important, and Maven can find the required dependencies according to the coordinates.

2. Type: the type of dependency, corresponding to the packaging defined by the project coordinates. In most cases, this element does not need to be declared, and its default value is jar.

3. Scope: The scope of dependence. There are three commonly used ones:

  • compile: Compile the dependency range, if not specified, the dependency range will be used by default. Maven dependencies using this dependency range are valid for the three classpaths of compiling, testing, and running
  • test: Test dependency range, only valid for test classpath, this type of dependency cannot be used when compiling the main code or running the project
  • provided: The dependency scope has been provided. The Maven dependency using this dependency scope is valid for compiling and testing the classpath, but invalid at runtime. A typical example is servlet-api. This dependency is needed when compiling and testing the project, but when running the project, since the container is already provided, there is no need for Maven to introduce it again and again.
  • runtime: runtime dependency range, valid for test and runtime, invalid at compile time

4. Optional: mark whether the dependency is optional. When it is true, it means it is an optional dependency. If project A depends on project B, project B depends on project X and Y, and B's dependencies on X and Y are optional dependencies. Then X and Y will have no effect on A, that is, no dependency transfer will take place.

5. Exclusions: Used to exclude transitive dependencies. It should be noted that when declaring exclusion, only the groupId and artifactId are required, and the version element is not needed. This is because only the groupId and artifactId are needed to uniquely locate a certain one in the dependency graph. rely.

There are many things that depend on this one. For a good project, it is also very important to manage the dependencies between multiple projects. The introductory chapter will record this point first.

 

Summary of Maven commonly used commands

  • mvn clean compile: delete the /target directory and compile the main code of the project
  • mvn clean test: execute all test code
  • mvn clean package -D maven.test.skip=true: package, but do not execute or compile test cases
  • mvn clean package -U -D skipTests: package and update the snapshot, do not execute test cases, but compile test case classes to generate corresponding class files under target/test-classes.
  • mvn clean install: deploy the finished package to the local maven warehouse for use by other projects
  • mvn clean deploy: deploy the finished package to the local maven warehouse and remote maven private server warehouse
  • mvn dependency:tree: View dependency tree
  • mvn dependency:tree -D output=*.txt: View the dependency tree and output the tree to the text

 

Guess you like

Origin blog.csdn.net/m0_38001814/article/details/103831721