第1章 Maven项目构建

Maven的两个核心功能:项目构建, 依赖(jar包)管理。

1.1 项目构建

在进行项目开发时,我们也会兼顾项目管理的工作,如添加依赖(jar包)、编译源码、单元测试、项目部署等操作。这一系列的操作就统称为“项目构建”

第1章 Maven项目构建​_java

1.2 Maven是什么

Maven是一个项目构建工具。使用Maven可以自动化地完成项目构建。学习到本章后半段就会体会到

1.3 Maven的作用

A. 项目构建:自动化地对项目进行编译、测试、打包、部署

B. 依赖管理:管理jar包,解决jar包之间的冲突(多个相同的jar,却有不同的版本)

1.4 Maven项目的结构

不同IDE的构建目录各不相同,以下是随便写得例子,但是能说明问题:

eclipse

JBuilder

NetBeans

idea

...

src bin

src output

src classes

src target

...

而Maven的一个伟大之处在于,它统一了全世界的java项目结构:

第1章 Maven项目构建​_maven_02

1.5 安装Maven

因为Maven是Java开发的,所以必须先安装好JDK并配置好JAVA_HOME环境变量!

1.5.1 下载Maven

Maven下载地址: https://maven.apache.org/download.cgi

第1章 Maven项目构建​_java_03

下载Maven后,解压到本地磁盘,解压目录中不要含有中文,也不要含有空格,解压后的目录如下:

第1章 Maven项目构建​_maven_04

1.5.2 环境变量

添加MAVEN_HOME环境变量,用于指定Maven的安装目录

第1章 Maven项目构建​_xml_05

修改Path环境变量,在其中追加Maven的bin目录

第1章 Maven项目构建​_maven_06

在命令行中输入"mvn -v",能看到以下内容,就说明Maven环境配置好了

第1章 Maven项目构建​_xml_07

1.6 阿里云镜像

在后续的学习中,Maven会从中央仓库下载所需的资源。但是Maven中央仓库下载速度非常慢,所以我们要指定一个下载速度较快的Maven仓库:Maven阿里云镜像仓库,打开Maven根目录下的conf目录,打开settings.xml,在mirrors元素中加入以下内容:

<mirror>

<id>nexus-aliyun</id>

<mirrorOf>central</mirrorOf>

<name>Nexus aliyun</name>

<url>http://maven.aliyun.com/nexus/content/groups/public</url>

</mirror>

1.7 Maven Hello Wolrd

手动创建一个Maven项目,编写代码,编译,并运行。注意目前手动创建MAVEN项目只是为了练习,后续我们会直接使用idea工具创建MAVEN项目的!

17.1 创建目录结构

第1章 Maven项目构建​_java_08

注意:由于Maven是Java编写的,所以Maven自然地把项目当做一个对象来看待,而pom.xml就是一个用于描述当前项目对象的配置文件,每个Maven项目都必须有一个pom.xml配置文件

1.7.2 编写pom.xml

pom是项目对象模型(Project Object Model)的简称,一个典型的pom.xml配置文件如下:

<?xml versinotallow="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:schemaLocatinotallow="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.gao</groupId>

项目名 -->

<artifactId>foo</artifactId>

版本号:大版本.小版本.里程碑版本 -->

<version>0.0.1-SNAPSHOT</version>

打包方式,取值可以是:jar、war、pom -->

<packaging>jar</packaging>

</project>

里程碑版本

说明

SNAPSHOT

开发版

alpha

内部测试版

beta

公开测试版

Release

发布版

1.7.3 编写Java类

在foo\src\main\java\com\gao\demo目录下创建一个App.java,内容如下:

第1章 Maven项目构建​_xml_09

1.7.4 编译

进入命令行,进入pom.xml文件所在目录,编译Java源文件

mvn compile

第1章 Maven项目构建​_maven_10

注意:

1. 第一次使用mvn compile命令时,会下载对应的插件,下载到本地仓库中

2. 命令mvn compile会自动调用javac对项目中所有的Java源文件进行编译

3. Maven知道Java源文件的位置在哪,因为Maven约定了Java源文件必须在src/main/java下

4. 编译好的字节码文件会存放到target/classes下,这也是约定

5. 注意以上的警告:使用平台相关的字符编码GBK,构建项目是与平台相关的,我们构建项目不应该与平台相关,所以在pom.xml中再加入以下配置(在</project>上面添加即可)

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

</properties>

第1章 Maven项目构建​_xml_11

6. 执行mvn命令时,必须在进入pom.xml文件所在目录!进入pom.xml文件所在目录!进入pom.xml文件所在目录!

1.7.5 运行

进入命令行,进入pom.xml文件所在目录,运行程序

mvn exec:java -Dexec.mainClass="com.gao.demo.App"

注意:

1. 第一次使用该命令,会下载对应的插件

2. -Dexec.mainClass用于指定包含main方法的类的“全限定名”,也就是“包名+类名”

3. Maven知道去target/classes目录下找com.gao.demo.App类,这也是约定

第1章 Maven项目构建​_xml_12

1.8 约定大于配置

Maven采用了约定大于配置的方式。也就是只要我们使用Maven来管理一个项目,那么该项目中源代码的位置,字节码的位置,配置文件的位置都是固定的,如下,以下一个名为foo的项目为例

目录

说明

/foo/

存放pom.xml

/foo/src/main/java

存放Java源代码

/foo/src/main/resources

存放配置文件,比如mybatis-config.xml

/foo/src/main/webapp

web应用根目录,等价于WebContent

/foo/src/test/java

存放测试代码

/foo/src/test/resources

存放测试用的配置文件

约定大于配置的优点就是,配置大大减少了。

1.9 配置Maven本地仓库

Maven的本地仓库默认在C盘下,这样如果将来我们重做了系统,格式化了C盘,则仓库中的依赖也会全部丢失。在用户的家目录下可以看到这默认的本地仓库,我们可以将该仓库删除

第1章 Maven项目构建​_java_13

然后我们直接把Maven的仓库位置修改到C盘以外的位置,我个人习惯把Maven的本地仓库放在Maven安装目录下的respository目录下,打开Maven根目录下的conf文件夹下的settings.xml,添加以下配置:

第1章 Maven项目构建​_maven_14

再次编译、运行Maven项目,会发现资源下载到了D:\apache-maven-3.8.4\repository下

第1章 Maven项目构建​_maven_15

1.10 依赖坐标

当我们把一个依赖的坐标写入pom.xml中的dependencies元素中后,在编译时Maven就会为我们下载对应的依赖。这个依赖会下载到本地仓库中,而不是下载到项目中。始终记住,项目中没有任何jar。项目中顶多只有依赖的坐标。

示例1:引入junit依赖

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.13.2</version>

<scope>test</scope>

</dependency>

第1章 Maven项目构建​_java_16

注意,引入一个依赖时,也会同时把该依赖相关的其他依赖一起引入进来

示例2:引入mysql依赖

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>8.0.27</version>

</dependency>

第1章 Maven项目构建​_xml_17

中央仓库地址: https://mvnrepository.com/

通过依赖坐标,可以在本地仓库找依赖,如果本地仓库没有,则可以继续拿着依赖坐标去远程仓库找!所以依赖坐标就是用来找依赖的!所以依赖坐标必须唯一!

1.11 Maven常用命令

Maven的命令格式如下:

mvn [plugin-name]:[goal-name]

命令

描述

mvn -v

显示Maven版本信息

mvn compile

编译src/main/java下的所有Java源文件

mvn clean

清除target

mvn test

执行src/test/java下的测试用例

mvn package

打包项目,在target下生成jar或war

mvn install

将打包好的jar或war存入到本地仓库中,供其他Maven项目使用

mvn compile 和 mvn clean我们已经熟悉了,下面学习其他的命令

1.11.1 mvn test

当执行mvn test命令时,Maven会自动去src/test/java目录下寻找所有名字以“Test”结尾的类,比如AppTest,然后再执行这些类中被@Test所标注的方法,这也是Maven的约定。所以我们按以下步骤测试这个命令:

步骤1:在src\test\java下创建com.gao.demo.AppTest类,在类中创建一个test方法,在其上添加一个@Test注解,注意使用@Test注解,必须先引入它:import org.junit.Test

第1章 Maven项目构建​_maven_18

步骤2:在pom.xml文件所在目录下,键入mvn test命令

第1章 Maven项目构建​_maven_19

1.11.2 mvn package

mvn package 用于打包Maven项目

第1章 Maven项目构建​_maven_20

第1章 Maven项目构建​_xml_21

可以看到在打包之前,先进行了test,如果想跳过test,则加入参数即可:

mvn package -Dmaven.test.skip=true

第1章 Maven项目构建​_xml_22

1.11.3 mvn install

mvn install 用于把当前Maven项目先打包,然后存入到本地仓库中,以便让其他的Maven项目使用

第1章 Maven项目构建​_maven_23

第1章 Maven项目构建​_maven_24

其他的Maven项目就可以引入我们这个项目的坐标,从而使用其中的类了。

1.12 Maven生命周期

Maven有3套生命周期:1. 默认生命周期;2. clean生命周期;3. site生命周期(不学)。

每个生命周期都包含多个阶段。比如默认生命周期的阶段包含:compile、test、package、install。当执行一个阶段的时候会先执行该阶段之前的所有阶段。比如在执行mvn test时,就会先执行compile阶段,再执行test阶段。比如在执行mvc install阶段的时候,就会先执行compile、test、package阶段,以此类推。

1.13 Maven插件和目标

我们已经知道,Maven的默认生命周期包含以下几个阶段:compile、test、package、install,而对于每个阶段的实现,Maven并没有写死,而是交给插件来完成,如下图所示:

第1章 Maven项目构建​_java_25

深入一点,一个Maven插件就是一个或多个目标的集合。每个目标都完成一个独立的任务,更确切地说,Maven生命周期中的各个阶段是由插件中的某个特定目标完成的,如下图所示:

第1章 Maven项目构建​_java_26

Maven有默认的插件,用默认插件的目标来实现各个阶段要做的事情。

示例1:插件的使用

<?xml versinotallow="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:schemaLocatinotallow="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.gao</groupId>

<artifactId>foo</artifactId>

<version>0.0.1-SNAPSHOT</version>

<packaging>war</packaging>

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

</properties>

<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-source-plugin</artifactId>

<version>2.2.1</version>

<executions>

<execution>

<goals>

<goal>jar</goal>

</goals>

<phase>test</phase>

</execution>

</executions>

</plugin>

</plugins>

</build>

</project>

可以看出,插件也是有坐标的。同时我们可以将插件中的某个目标绑定到生命周期的某个阶段上,当执行到该阶段时,对应的插件目标就会执行了

第1章 Maven项目构建​_maven_27

第1章 Maven项目构建​_xml_28

示例2:插件的目标也可以独立执行

第1章 Maven项目构建​_maven_29

1.15 Maven概念模型

第1章 Maven项目构建​_maven_30

1.16 Maven的优点

A. 项目构建:自动化地对项目进行编译、测试、打包、部署

B. 依赖管理:管理jar包,解决jar包之间的冲突(多个相同的jar,却有不同的版本)