前言
本期内容是上期内容的一个延伸,小黑通过从0到1创建一个Maven项目,来实际操作一下。如果你也是初学Maven,也可以按照我的操作步骤来试试。
以下是本期的主要内容:
- 从0到1创建一个maven项目
- maven目录结构
- 常见maven命令
- 如何构建一个Fat Jar
- Maven内存设置
Maven hello world!
就叫这个项目maven-hello-world
吧。
创建项目文件夹
一个Maven项目本质上就是pom文件和一个文件夹
,我们先找一个位置,建立一个文件夹,就叫maven-hello-world
。
创建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没问题。
创建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文件就存放在这个文件夹中,还有许多临时文件(例如,一个包含所有已编译类的类目录)。
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 | 打印出项目中依赖 |
mvn dependency:tree -Dverbose -Dincludes=com.fasterxml.jackson.core | 打印出项目中依赖 |
mvn dependency:build-classpath | 根据pom.xml文件中配置的依赖项,输出依赖项的classpath。 |
需要注意,执行maven的clean命令时,会将target中的所有文件删除,这意味着会丢失之前已经编译构建过的类。如果项目很大,可能需要花费较多的时间构建。但是一般在项目部署之前,为了保证所有的内容都是重新构建的,一般都会执行clean。
Build Life Cycles, Phases和Goals
这三者的关系可以按下图表示:
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项目,或者计算机的内存比较小,可能需要调整Maven的内存限制。从Maven 3.3版本,可以在jvm.config
文件中设置内存限制。jvm.config
位于项目目录中的.mvn
目录中。
在jvm.config
文件中,可以使用以下参数控制Maven的内存限制:
-Xmx2048m -Xms1024m
可以通过调整-Xmx
和-Xms
的值控制内存使用大小。
最后
以上是本期的全部内容,下期再专门讲一下Maven依赖相关的一些问题,如果对你有帮助,点个赞是对我最大的鼓励!