一、基本概念:
- 主用途:自动化构建Java项目、依赖管理、项目管理。
- 构建流程:清理、编译、测试、生成报告、打包、部署。
- 依赖管理、项目管理:提供免费的中央仓库,自动下载构件。
-
约定优于配置:省去命名、规划目录结构的额外成本。
二、使用:
1. pom.xml
- 是接触最多的,也是maven的核心,spring boot也推荐使用maven,以idea直接创建spring boot项目的pom文件为例,一行一行说。
- 前三行:
xml文件头
、根元素project
(便于快速编辑pom)、modelVersion
(目前maven3必须是4.0.0),这些一般不需要特别关注。
-
parent元素
:主要用于依赖版本继承,如果这个项目使用了parent项目里的依赖,而且版本一致则不需要写版本号。
-
parent > groupId
:用于指定父项目的组,组一般标明公司(组织)和项目名,用于在maven中定位项目。
-
parent > artifactId
:组中的唯一ID,artifactId也可以理解成groupId的一个模块名。
-
parent > version
:声明版本,其中也会有标明测试、正式等等版本的区分,一般我的习惯是例如 0.0.1-SNAPSHOT就是测试版本,1.0.0-RELEASE就是第一个上线版本,1.0.1-RELEASE、1.1.0-RELEASE...
-
groupId、artifactId、version
组合可以工程在maven里唯一的定位坐标。
-
relativePath
:代表始终从仓库中获取parent,这句话是网上搜到的,我自己暂时没理解到。
- 和parent下声明类似,根元素下的
groupId、artifactId、version
用于声明本项目信息。
-
name、description
:这两个元素不必须,网上查说是对文档功能有用,我一般直接删除。
-
properties > java.version
:spring boot用于声明Java版本,也可以用于统一使用,类似于Java成员变量,默认就是1.8,所以不写也没问题。
-
dependencies
:引入依赖的主要部分,样例里引入了spring-boot-starter
和spring-boot-starter-test
,依赖的定位声明上面提到了,因为声明了parent元素,所以版本从parent继承下来,还出现了一个scope
元素,后续说明。
-
plugins
:声明插件,spring-boot-maven-plugin是为spring-boot项目提供maven支持的插件。
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.oliver.maven</groupId>
<artifactId>maven-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>maven-test</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2. 项目目录结构:
- 上面是idea创建的spring boot项目,项目结构上
src/main/java
是业务主目录、src/main/resources
是资源配置目录、src/test/java
是测试类目录、还包括pom.xml
,这些目录包含了项目基本的结构要求,上面提到的约定优于配置,没有特别需求不需要改动目录结构,到具体位置写代码就行。
- 除了spring boot项目,还有最基本的maven项目,一般idea创建
maven-archetype-quickstart
即可,也可以敲mvn命令创建,目录结构比spring boot简单一些。
3. dependency元素里<scope>
的作用:
- 样例里提到了
<scope>
,maven管理的项目在编译、测试、运行阶段
会各使用一套classpath,也就是说不同阶段依赖会有不同,声明<scope>
会指定某些阶段加入指定依赖到classpath,因为有些阶段并不需要使用全部,一共有5种。
-
compile
:默认的级别,所有依赖都加入classpath,少了依赖项目运行不起来,多了一般只会臃肿一些,所以如果不想改<scope>
默认就可以了。
-
test
:测试阶段有效,如样例的spring-boot-starter-test,编译和运行并不需要测试包。
-
provided
:编译和测试阶段有效。如lombok。
-
runtime
:测试和运行时有效。
-
system
:和provided
作用阶段一致,只是调用的是本机依赖,限制性大,很少用。
4. 依赖的传递性和调解:
- 样例项目中依赖了spring-boot-starter,算作直接依赖,通过idea或者其他IDE点进去发现,spring-boot-starter内部也会有自己的直接依赖,这样就形成了传递,传递的依赖也会作用到样例项目,不过受
<scope>
元素的限制,如spring-boot-starter是默认的compile
,spring-boot-starter的内部依赖就会按自身<scope>
就会原封不动的作用于样例项目,具体范围传递规则不都列了。
- 复杂依赖情况下,传递会遇到同版本的依赖,第一原则是取依赖路径上就近的版本,如果继续冲突就按pom声明顺序确定。
5. 仓库
- 仓库分远程仓库和本地仓库, 私服是特殊的远程仓库,中央仓库是默认的远程仓库。
- 默认本地仓库没有构件时,就会找远程仓库。
- 默认maven本地仓库会存放在windows和linux的用户目录下
.m2/repository
文件夹里,默认隐藏。
-
~/.m2/repository
同级目录下可以放置setting.xml
进行相关仓库配置,默认不存在需要从maven安装目录的conf
文件夹复制过来,可以设置本地仓库位置、远程仓库地址(如私服)、远程仓库的认证信息等等。远程仓库地址也可以直接配在项目pom文件里,根据需要使用。
- 私服:很多公司都会有自己的maven私服,比如可以上传公司内部的构件,不想被公开,还可以提高下载速度,有时候中央仓库下载很慢。如果不想自己搭建,也可以选择国内的远程仓库很多公司都有提供。
6. 生命周期
- maven拥有三套独立的生命周期,
clean
、default
、site
。
- 每个周期都包含多个阶段,后面的阶段会依赖前面的阶段,但各个周期是相对独立的。
- maven为每个周期里必要的阶段绑定默认插件,例如清理、编译、打包、项目插件推送到本地仓库等等阶段都有,也可以自定义绑定,在pom.xml的
buile
元素里配置,如样例里spring-boot-maven-plugin
就是spring boot专门使用的插件,可以提供spring boot打包等功能。
7. 聚合与继承
- 样例pom的parent是
spring-boot-starter-parent
没有其他继承关系,再大一点项目就会涉及到子模块的划分。
- 子模块都应该使用相同的
groupId
,通过artifactId
进行区分,artifactId
一般按功能命名。
- 像样例pom里继承
spring-boot-starter-parent
一样,子模块就不用声明依赖版本了,但这个parent肯定远远不够,项目一般还会有其他三方依赖,所以分子模块的项目也需要自定义一个父模块进行统一的配置。可以继承的除了依赖版本还有仓库配置、声明的properties
变量、插件等等。
- 自定义的父模块有几个需要注意的常用元素:www.jianshu.com/p/e9791e68f943 这篇里有写。
8. 约定优于配置
- 这一观点很多地方都适用,例如各种通讯协议就是约定,所以后续的人在使用时会根据自己的需要使用http、tcp、udp或者ftp等等就不需要自己再造轮子。
- 上面也提到了,如maven里的约定:
-
src/main/java
是业务主目录
-
src/main/resources
是资源配置目录
-
src/test/java
是测试类目录
-
target/classes
是编译输出目录
-
target
是打包输出目录
- 默认打包成jar等等
- maven作为cicd其中的一环,经常和Jenkins、gitlab等一起使用,如果涉及到容器化还会涉及到docker、k8s等,还有maven私服Nexus的基本部署使用等等,待续。
网友评论