<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.0modelVersion>
<groupId>com.lingz.cloudgroupId>
<artifactId>gatewayartifactId>
<version>2.1.5.SNAPSHOTversion>
<name>cloud-gatewayname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencyManagement>dependencyManagement>
<dependencies>dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
1、groupId、artifactId、version
groupId、artifactId、version 三者定义了一个项目的坐标。
groupId: 公司的一个项目组,比如我公司下的cloud项目 → com.lingz.cloud
artifactId: 在项目中的唯一模块,比如cloud项目组里的网关gateway → gateway \ 注册中心 → registry-center
version: 即这个项目组里这个模块的版本,即 artifact 的版本
version
* SNAPSHOT ,快照,当前项目模块还在开发中,不稳定版本。
PS:
在<dependency>中的<scope>,指生效范围:
* test 范围,只测试代码有用,主代码使用编译会出错。
* 默认 compile , 即主代码和测试代码都有效。
2、打包(添加主类)
默认下,打成jar不会含有test目录下的,注意 ,/main/java 和 /resources 打包后不见了,即从他们的子目录开始打包,他们只是约定的目录而已。
- 包的路径一般为 groupId 的名称,即 com.lingz.cloud
- 主类的名字就和 artifactId 一致,即 Cloud.class ( 都是约定,只是更清晰。)
//单纯打包可能出现找不到主类的情况,这时候可以在 里面添加插件
3、一些命令
(1)mvn clean compile 编译主代码
clean
- 告诉maven清除输出目录 target/
compile
- 编译项目主代码
执行顺序
clean:clean 清除 target/
resources:resources (后续讲)
compiler:compile 将项目主代码编译到 target/classes目录下
// 这里 X:Y 代表 X插件下的Y目标
(2)mvn clean test 编译执行测试代码
生命周期执行顺序
clean:clean
resources:resources
compiler:compile
resources:testResources
compiler:testCompile //生成编译后的二进制测试代码,在target/test-classes下。
surefire:test // surefire是Maven负责执行测试的插件,这里执行 CloudTest.class 类,并输出执行结果
(3)mvn clean package 编译打包
没有指定打包格式时,默认打包成 jar包:
jar:jar
在package打包之前,还会执行test,可以在idea里面关掉。
(4)mvn clean install 将打包的jar安装到Maven本地仓库 !! !
生命周期
···
jar:jar
install:install //添加到本地仓库。可以在对应文件夹看到有pom和对应的jar
//会根据pom配置自动下载所需的依赖构件,所以可以测试是否跑的通
在执行完打包后,会将打包结果放到本地仓库,这样就能给其他项目引用了,只要添加<dependency>即可。
二、Maven坐标
-
Maven坐标包括 groupId 、artifactId 、version 、packaging 、 classifier
-
PS: classifier = jdk15 ; 指定的是Java5
1、坐标元素详解
//groupId(必须)
可以理解为定义这个Maven项目所在的项目组,由公司.项目组定义。项目组里可以有很多模块,就是下面的artifact
//artifactId(必须)
指定这个Maven项目所属的模块。比如 SpringFramework 这个项目组里的 core 核心模块。推荐用项目组+模块名命名,即 spring-core ,这样打包生成就是 spring-core-0.0.1.jar
//version(必须)
该Maven项目的版本。
//packaging(可选)
定义Maven项目的打包方式,默认jar。打包方式会影响构建的生命周期(使用不同的插件:目标)
//classifier(不可直接定义)
- 不能直接定义,附属构件不是项目默认生成,而是由附加的插件帮助生成。
- 作用是生成项目的一些附属构件,如生成spring-core-0.0.1-javadoc/sources.jar
- 这个 javadoc 、 sources就是两个附属构件的classifier 。
//最终生成的文件名 = artifactId + version [-classifier] . packaging
三、依赖配置
1、基本结构
... ... ... ... ... ... ... ... ... ... ... true 代表这个依赖是可选的,比如B里面有两个依赖是 optional = true , 而A依赖B 同时A需要B中这两个可选的依赖的其中一个(二选一),那么A不会直接用B去引用这两个中的一个 而是显示在A中的依赖声明其中一个依赖,这就是 可选依赖。
2、依赖范围
主代码会使用一套classpath , 测试代码也会使用一套classpath ,实际运行的时候又会使用一套 classpath
即:编译classpath 、 测试classpath 、 运行classpath
(编写代码 和 运行代码是不一样的阶段 !!!)
// compile - 编译依赖范围 。 - 默认,即未指定时,编译、测试、运行时都需要这个依赖。 // test - 测试依赖范围 - 仅测试classpath有效。 // provided - 已提供依赖范围 - 编译classpath 、 测试classpath 都有效,但是运行classpath无效!!!如 servlet-api,运行时容器已经提供。 // runtime - 运行时依赖范围 - 编译主代码时无效,但是测试 classpath 和运行classpath 有效 - 如JDBC驱动实现。项目编写时只需要JDK提供的JDBC接口,只有运行项目时才需要实现上述接口的具体JDBC驱动 // system - 系统依赖范围 - 和 provided 的依赖效果完全一致。(仅运行时classpath 无效。) - 不同的是:必须通过 systemPath元素显示指定依赖文件的路径。 - 此类依赖往往和中央Maven仓库无关,而是与本机系统绑定,构建是不可移植,少用。 - systemPath元素可以引入环境变量。 // import - 导入依赖范围。 - 不会对三种 classpath 产生实际影响。
四、依赖传递性
Maven会解析各个直接依赖的POM,将那些必要的间接依赖,以传递性依赖的形式引入到项目中(A→B→C,则以传递性依赖形式引入C)。
五、依赖调解
若有 A→B→C→X(1.0)和 A→D→X(2.0),则会选第二条,根据“路径最近者优先” 。
如果路径相同,则根据POM中依赖声明的顺序决定谁先被解析,顺序越前越先。
六、排除依赖
B引用了一个老版本依赖C(1.0-SNAPSHOT) ,而A需要依赖B,但是不想用这个老版本C,所以可以在B排除,然后自己引入一个新的C
com.lingz.cloud B 1.0 com.alibaba.utils C com.byte.utils C 2.0
七、POM自定义常量(依赖归类)
就是在properties里面配置一些常量,一般可以是版本号,然后在下面的依赖使用
... ... 5.1.2 org.springframework spring-core ${springframework.version}
八、依赖分析
mvn dependency:list mvn dependency:tree mvn dependency:analyze