前言

本期内容是​​上期内容​​的一个延伸,小黑通过从0到1创建一个Maven项目,来实际操作一下。如果你也是初学Maven,也可以按照我的操作步骤来试试。

以下是本期的主要内容:

  1. 从0到1创建一个maven项目
  2. maven目录结构
  3. 常见maven命令
  4. 如何构建一个Fat Jar
  5. Maven内存设置

Maven hello world!

就叫这个项目​​maven-hello-world​​吧。

创建项目文件夹

一个Maven项目本质上就是​​pom文件和一个文件夹​​​,我们先找一个位置,建立一个文件夹,就叫​​maven-hello-world​​。

【Maven专栏系列】Maven项目从0到1_Java

创建pom文件

接下来我们在这个文件夹中创建一个pom.xml文件。

接下来我们在这个文件夹中创建一个pom.xml文件。

<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.heiz</groupId>
<artifactId>maven-hello-world</artifactId>
<version>1.0.0</version>

</project>

这是一个最基本的pom.xml文件。在这个文件中我们定义了这个项目的GAV(groupId,artifactId,version),别人如果需要依赖这个项目,则在依赖中加入我们的GAV就可以。

测试pom文件

现在为了保证我们文件的正确性,我们可以执行命令来测试一下。在当前目录打开命令行,然后执行下面的命令:

mvn clean

​mvn clean​​命令将清除项目目录中所有以前的临时构建文件。因为我们的项目是全新的,所以没有文件需要删除。如果命令行输出下面的成功信息表示我们的pom.xml没问题。

【Maven专栏系列】Maven项目从0到1_jar文件_02

创建Java源代码目录

接下来我们就可以建立Java源代码的文件目录了。按照如下层级建立文件夹。

- src
- main
-java

创建一个Java文件

然后我们在​​src/main/java​​文件夹中创建一个再创建一个文件夹作为我们代码的包,我们就叫它​​hello​​吧,然后再​​hello/​​建第一个Java代码文件​​HelloWorld.java​​。

package hello;

public class HelloWorld {
public static void main(String args[]){
System.out.println("Hello World, Maven");
}
}

构建项目

现在我们就可以使用Maven命令来打包我们的项目了。回到项目的根目录​​maven-hello-world​​。进入命令行执行下面的命令:

maven package

这个命令将将编译Java源文件,并创建一个包含已编译Java类的JAR文件。项目根目录中会创建一个target文件夹,JAR文件就存放在这个文件夹中,还有许多临时文件(例如,一个包含所有已编译类的类目录)。

【Maven专栏系列】Maven项目从0到1_jar文件_03

【Maven专栏系列】Maven项目从0到1_Java_04

JAR文件的命名格式为​​artifactId-version​​,所以我们的项目Jar包名称为​​maven-hello-world-1.0.0.jar​​。

Maven目录结构

Maven有一套标准的目录结构,遵循这套标准很有用,也可以让别人在接手你的项目时更容易理解每个目录的作用。

标准目录结构

下面是一个最常用的maven目录结构,还有一些不太常用的目录我这里省略了。

project_dir
- pom.xml
- .mvn
- jvm.config
- src
- main
- java
- resources
- test
- java
- resources
- target

​project_dir​​是我们项目的根目录。

​.mvn​​是一个存放Maven配置文件的目录,比如jvm.config文件,可用于配置Maven用于构建项目的JVM。可以在这个文件中设置Maven内存限制。

​src​​是应用程序和测试源代码的根目录。

​src/main/java​​存放应用程序的源代码。应用程序需要的任何资源文件(例如​​properties​​文件)都放在​​src/main/resources​​目录中。资源文件可以通过​​classpath​​加载。

​src/test/java​​存放测试源代码。测试代码需要的任何资源文件(例如​​properties​​文件)都放在​​src/test/resources​​中。同样可以通过classpath加载。

​target​​包含Maven构建项目的所有输出内容。​​target​​还包含Maven在构建应用程序时所需的临时文件和中间文件。

也可以访问maven官网查看更全的目录信息。​​maven官方文件目录说明​

Maven命令

Maven包含大量可以执行的命令。Maven命令是Life Cycles、Phases和Goals的混合,因此有时候不太容易理解。因此,我将在本期内容中描述常见的Maven命令,并解释它们正在执行的Life Cycles、Phases和Goals。

常见的Maven命令

下面是一些常见的Maven命令,以及它们的功能描述。

maven命令

Description

mvn --version

打印maven版本

mvn clean

清除target目录中的构建结果

mvn package

构建项目并将生成的JAR文件放到target目录中。

mvn package -Dmaven.test.skip=true

构建项目并将生成的JAR文件放到target目录中。——在构建期间不运行单元测试。

mvn clean package

先清除target目录,然后构建项目并将生成的JAR文件放到target目录中。

mvn clean package -Dmaven.test.skip=true

先清除target目录,然后构建项目并将生成的JAR文件放到target目录中。——在构建期间不运行单元测试。

mvn verify

运行项目中所有的集成测试用例

mvn clean verify

先清除target目录,然后运行项目中所有的集成测试用例

mvn install

构建项目,并将生成的jar包保存到本地Maven仓库中

mvn install -Dmaven.test.skip=true

构建项目,并将生成的jar包保存到本地Maven仓库中,构建时不运行单元测试

mvn clean install

先清除target目录,构建项目,并将生成的jar包保存到本地Maven仓库中

mvn clean install -Dmaven.test.skip=true

先清除target目录,构建项目,并将生成的jar包保存到本地Maven仓库中,构建时不运行单元测试

mvn dependency:copy-dependencies

将依赖项从远程Maven仓库复制到本地Maven仓库。

mvn clean dependency:copy-dependencies

清除项目并将依赖项从远程Maven仓库复制到本地Maven仓库。

mvn clean dependency:copy-dependencies package

清除项目并将依赖项从远程Maven仓库复制到本地Maven仓库,然后打包项目。

mvn dependency:tree

根据pom.xml文件中配置的依赖项,打印出项目的依赖项树。

mvn dependency:tree -Dverbose

根据pom.xml文件中配置的依赖项,打印出项目的依赖项树。包括重复的传递依赖。

mvn dependency:tree -Dincludes=com.fasterxml.jackson.core

打印出项目中依赖​​com.fasterxml.jackson.core​​的依赖项。

mvn dependency:tree -Dverbose -Dincludes=com.fasterxml.jackson.core

打印出项目中依赖​​com.fasterxml.jackson.core​​的依赖项,包括重复的传递依赖。

mvn dependency:build-classpath

根据pom.xml文件中配置的依赖项,输出依赖项的classpath。

需要注意,执行maven的clean命令时,会将target中的所有文件删除,这意味着会丢失之前已经编译构建过的类。如果项目很大,可能需要花费较多的时间构建。但是一般在项目部署之前,为了保证所有的内容都是重新构建的,一般都会执行clean。

Build Life Cycles, Phases和Goals

这三者的关系可以按下图表示:

【Maven专栏系列】Maven项目从0到1_Java_05

Maven包含三个主要的​​Build Life Cycles​​:


  • clean
  • default
  • site

在每个​​Build Life Cycles​​中都包含​​Phases​​,在每个​​Phases​​中都包含​​Goals​​。

可以理解为Maven将需要做的事情按照粒度进行了划分,将​​Goals​​组合成​​Pahses​​,然后将​​Phases​​组合成​​Life cycles​​。

构建一个Fat Jar

首先说一下什么是​​Fat Jar​​?这里我们还是用我们的​​maven-hello-world​​项目来举个例子。

假设我现在需要将​​Guava​​加入到我的项目依赖中,我们在​​pom.xml​​中添加​​Guava​​的依赖。

<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.heiz</groupId>
<artifactId>maven-hello-world</artifactId>
<version>1.0.0</version>

<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
</dependencies>
</project>

然后我们使用​​mvn package​​进行打包。完成之后我们会在​​target​​目录中找到我们的​​maven-hello-world-1.0.0.jar​​,如果你使用解压工具打开看的话,这个Jar包中是没有​​guava​​包相关的文件的。

那么我们在某些场景中,比如需要发布一个微服务,如果没有将依赖项打包到一个JAR文件中,那么需要将其他依赖项单独的上传到服务中,这很麻烦。如果能够将所有的依赖和项目代码一起打包到一个JAR文件中,只需要上传一个文件就可以启动服务,这会很方便。

Fat JAR就是这种将所有依赖打包到一起的JAR文件。

要想构建一个Fat JAR,需要修改我们的​​pom.xml​​。通过在POM文件的​​plugins​​部分中包含​​maven-assembly-plugin​​:

<build>
<finalName>maven-hello-world</finalName>
<plugins>
<!-- other Maven plugins ... -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<archive>
<manifest>
<!--这里指定要运行的main类-->
<mainClass>hello.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>
</plugins>
</build>
<build>    <finalName>maven-hello-world</finalName>    <plugins>        <!-- other Maven plugins ... -->        <plugin>            <groupId>org.apache.maven.plugins</groupId>            <artifactId>maven-assembly-plugin</artifactId>            <version>3.1.1</version>            <configuration>                <archive>                    <manifest>                        <!--这里指定要运行的main类-->                        <mainClass>hello.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>    </plugins></build>复制代码

​maven-assembly-plugin​​​配置中的元素包含​​descriptorRef​​,它告诉Maven怎样进行组装。

​jar-with-dependencies​​表示构建一个带有依赖项的JAR文件,也就是Fat JAR。

​execution​​表示这个插件应该在哪个阶段和目标执行。

将上面的配置添加到我们的​​maven-hello-world​​​的pom.xml文件中,再执行一次​​mvn clean package​​。执行成功之后,在target目录中会出现一个Fat Jar。

【Maven专栏系列】Maven项目从0到1_xml_06

Maven内存设置

如果要构建一个大型Maven项目,或者计算机的内存比较小,可能需要调整Maven的内存限制。从Maven 3.3版本,可以在​​jvm.config​​​文件中设置内存限制。​​jvm.config​​​位于项目目录中的​​.mvn​​目录中。

在​​jvm.config​​文件中,可以使用以下参数控制Maven的内存限制:

-Xmx2048m -Xms1024m

可以通过调整​​-Xmx​​​和​​-Xms​​的值控制内存使用大小。

最后

以上是本期的全部内容,下期再专门讲一下Maven依赖相关的一些问题,如果对你有帮助,点个赞是对我最大的鼓励!