1 依赖
1.1 denpendency包含的元素
名称 | 作用 | 备注 |
---|---|---|
groupId | 当前Maven项目隶属的实际项目 | 基本坐标 |
artifactId | 实际项目中的一个Maven项目模块 | 基本坐标 |
version | 版本号 | 基本坐标 |
type | 依赖的类型,对应于项目坐标定义的packaging(巨) | jar, war, pom,默认是jar |
scope | 依赖的范围 | compile(编译依赖范围), test(测试依赖范围), provided(已提供依赖范围), runtime(运行时依赖范围), system(系统依赖范围), import(导入依赖范围), 默认是compile |
optional | 标记依赖是否可选 | 可选的依赖不能被依赖传递 |
exclusions | 依赖排除 | 一个exclusions可以包含一个或者多个exclusion子元素,即排除一个或者多个传递性依赖 |
1.2 依赖范围 scope
名称 | compile | test | runtime | 说明 |
---|---|---|---|---|
compile | √ | √ | √ | 对compile, test, runtime三个阶段都有效 |
test | √ | 只在test阶段有效 | ||
runtime | √ | 只在runtime阶段有效 | ||
provided | √ | √ | compile和test阶段有效 | |
system | √ | √ | 该依赖和本机系统绑定,所以必须使用systemPath元素显示地指定依赖文件的路径,使用这个依赖范围会造成构建的不可移植性。 | |
import | dependencyManagement元素下才有用,该范围的依赖通常指向一个pom,作用是把目标pom中的dependencyManagement配置导入到当前的pom,并且type配置为pom |
java程序有三种classpath,分别是compile classpath,test classpath,runtime classpath,如上表不同的依赖范围支持不同的classpath
假设A依赖于B,B依赖于C,我们说A对于B是第一直接依赖,B对于C是第二直接依赖,A对于C是传递性依赖
如下图,最左边一列表示第一直接依赖范围,最上面一行表示第二直接依赖范围,中间交叉单元格表示传递性依赖范围。
依赖范围影响传递性依赖
可以用mvn dependency:tree,可以看到各个依赖的依赖传递以及依赖范围
[INFO] com.sankuai.sjst.crm:crm-common:jar:1.0.0-SNAPSHOT
[INFO] +- org.jmockit:jmockit:jar:1.9:test
[INFO] +- junit:junit:jar:4.12:test
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- org.springframework:spring-test:jar:4.2.6.RELEASE:test
[INFO] | \- org.springframework:spring-core:jar:4.2.6.RELEASE:compile
[INFO] +- com.fasterxml.jackson.core:jackson-core:jar:2.1.0:compile
[INFO] +- com.fasterxml.jackson.core:jackson-databind:jar:2.1.0:compile
[INFO] +- com.fasterxml.jackson.core:jackson-annotations:jar:2.1.0:compile
[INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:compile
[INFO] +- org.springframework:spring-context:jar:4.2.6.RELEASE:compile
[INFO] | +- org.springframework:spring-aop:jar:4.2.6.RELEASE:compile
[INFO] | | \- aopalliance:aopalliance:jar:1.0:compile
[INFO] | +- org.springframework:spring-beans:jar:4.2.6.RELEASE:compile
[INFO] | \- org.springframework:spring-expression:jar:4.2.6.RELEASE:compile
[INFO] +- org.apache.commons:commons-lang3:jar:3.4:compile
[INFO] +- commons-collections:commons-collections:jar:3.2.2:compile
[INFO] +- commons-io:commons-io:jar:2.3:compile
[INFO] +- com.meituan.inf:xmd-log4j2:jar:1.1.3:compile
[INFO] | +- com.meituan.inf:xmd-common-log4j2:jar:1.1.2:compile
[INFO] | | \- org.slf4j:jcl-over-slf4j:jar:1.7.2:compile
[INFO] | +- org.slf4j:slf4j-api:jar:1.7.2:compile
[INFO] | +- org.apache.logging.log4j:log4j-slf4j-impl:jar:2.3:compile
[INFO] | +- org.apache.logging.log4j:log4j-api:jar:2.3:compile
[INFO] | +- org.apache.logging.log4j:log4j-core:jar:2.3:compile
[INFO] | \- org.apache.logging.log4j:log4j-1.2-api:jar:2.3:compile
1.3 依赖原则
1.路径最近者优先
2.第一声明者优先
2 仓库
maven仓库分类一个构件只有在本地仓库中才能由其他Maven项目使用,构件可以从远程仓库中下载,也可以将本地项目的构件install到本地的Maven项目中。
settings.xml的<localRepository>:定义本地仓库的地址
2.1依赖查找的顺序
① 在本地仓库中搜索,如果找不到,执行②,如果找到了则执行其他操作。
② 在中央仓库中搜索,如果找不到,并且有一个或多个远程仓库已经设置,则执行步骤 ④,如果找到了则下载到本地仓库中已被将来引用。
③ 如果远程仓库没有被设置,Maven 将简单的停滞处理并抛出错误(无法找到依赖的文件)。
④ 在一个或多个远程仓库中搜索依赖的文件,如果找到则下载到本地仓库已被将来引用,否则 Maven 将停止处理并抛出错误(无法找到依赖的文件)。
2.2 settings.xml 和pom.xml中仓库信息设置
依赖的下载与部署的仓库是在pom.xml文件中的<distributionManagement>和<repository>设置的,通常访问这些仓库是需要认证的,认证信息在settings.xml<server>元素中。
pom.xml
<distributionManagement>
<repository>
<id>xxx-nexus-releases</id>
<name>xxx Nexus Repository</name>
<url>http://maven.xxx.com/nexus/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>xxx-nexus-snapshots</id>
<name>xxx Nexus Repository</name>
<url>http://maven.xxx.com/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
在settings.xml中<server>元素的id必须与pom.xml中需要认证的<repository>的id完全一致。id将认证信息和仓库联系在一起了。
<server>
<id>xxx-nexus-releases</id>
<username>xxx</username>
<password>yyyy</password>
</server>
<server>
<id>xxx-nexus-snapshots</id>
<username>xxx</username>
<password>yyy</password>
</server>
pom.xml中设置了两个仓库,一个是release版本的仓库,一个是snapshots,如果release仓库Deployment Policy是“Disable
Redeploy”,那么release版本是不允许覆盖的。
所以当同样的release版本号二次发布的时候会报错,错误提示类似“Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project crm-onlinepay-client: Failed to deploy artifacts: Could not transfer artifact com.xxx.yyy:crm-onlinepay-client:jar:1.0.1 from/to xxx-nexus-releases (http://maven.xxx.com/nexus/content/repositories/releases/): Failed to transfer file: http://maven.xxx.com/nexus/content/repositories/releases/com/xxx/yyy/crm-onlinepay-client/1.0.1/crm-onlinepay-client-1.0.1.jar. Return code is: 400, ReasonPhrase: Bad Request. -> [Help 1]”
Maven2部署构件到Nexus时出现的Failed to transfer file错误 @周路敏
3 Maven模块的聚合与继承
<modules> 声明聚合 为了快速构建项目
<parent>声明继承 为了消除重复配置
我的onlinepay项目结构
最外面层的pom.xml是聚合pom,他的packaging方式必须是pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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>
<parent>
<groupId>com.xxx.yyyy.crm</groupId>
<artifactId>crm-parent</artifactId>
<version>1.0.4</version>
</parent>
<groupId>com.xxx.yyyy</groupId>
<artifactId>crm-onlinepay</artifactId>
<version>1.0.1</version>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<properties>
<project-client.version>1.0.1</project-client.version>
<project-web.version>1.0.1</project-web.version>
</properties>
<distributionManagement>
<repository>
<id>xxxx-nexus-releases</id>
<name>xxxx Nexus Repository</name>
<url>http://maven.xxx.com/nexus/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>xxxx-nexus-snapshots</id>
<name>xxx Nexus Repository</name>
<url>http://maven.xxx.com/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
<modules>
<module>crm-onlinepay-client</module>
<module>crm-onlinepay-web</module>
</modules>
</project>
onlinepay-client的pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.xxx.yyyy</groupId>
<artifactId>crm-onlinepay</artifactId>
<version>1.0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>crm-onlinepay-client</artifactId>
<version>${project-client.version}</version>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.sankuai.sjst.crm</groupId>
<artifactId>crm-common</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-archetype-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.4</version>
<configuration>
<attach>true</attach>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
onlinepay-web的pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.xxx.yyyy</groupId>
<artifactId>crm-onlinepay</artifactId>
<version>1.0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>crm-onlinepay-web</artifactId>
<packaging>war</packaging>
<name>${project.artifactId}</name>
<version>${project-web.version}</version>
.....
</project>
聚合和继承
3.3 反应堆
所有模块组成的一个构建结构是反应堆,反应堆的顺序与模块间的继承关系和声明顺序有关,如果模块间不存在继承关系,则反应堆的构建顺序是声明顺序,如果存在继承关系,则首先构建父模块。
crm-onlinepay-client和crm-onlinepay-web是子模块,crm-onlinepay是父模块
项目反应堆构建顺序
剪裁反应堆
-am, --alse-make 同时构建依赖于所列模块的模块
-amd, -alse-make-dependents 同时构建依赖于所列模块的模块
-pl, --projects <arg> 构建指定的模块,模块间用逗号分隔
-rf, -resume-from <arg> 从指定的模块恢复反应堆,也就是说从哪里开始构建
3.4 pom中可继承的元素
Maven继承的目的是为了消除重复,所以pom中大量的元素是可以被继承的。
groupId:项目组ID,项目坐标的核心元素
version: 项目版本, 项目坐标的核心元素
description: 项目的描述信息
organization: 项目的组织信息
inceptionYear: 项目的创始年份
url: 项目的URL地址
developers: 项目开发者信息
contributors: 项目的贡献者信息
distributionManagement: 项目的部署配置
issueManagement: 项目的缺陷跟踪系统信息
ciManagement: 项目的持续集成系统信息
scm: 项目的系统信息
mailingLists: 项目的邮件列表信息
properties: 自定义的maven属性
dependencies: 项目的依赖配置
dependencyManagement: 项目的依赖管理配置
repositories: 项目的仓库配置
build: 包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等
reporting: 包括项目的报告输出目录配置、报告插件配置等
所以crm-onlinepay项目会继承crm-parent里面的依赖等信息
4 灵活的构建
Maven提供属性,资源过滤和profile三种方式进行灵活的构建
4.1Maven属性
1.内置属性
${basedir}表示项目根目录,${version}表示项目版本
2.POM属性
(使用pom属性可以引用到pom.xml文件对应元素的值)
${project.build.directory}表示主源码路径;
${project.build.sourceEncoding}表示主源码的编码格式;
${project.build.sourceDirectory}表示主源码路径;
${project.build.finalName}表示输出文件名称;
${project.version}表示项目版本,与${version}相同;
3.自定义属性
在pom.xml文件的<properties>标签下定义的Maven属性
4.settings.xml文件属性
(与pom属性同理,用户使用以settings.开头的属性引用settings.xml文件中的XML元素值)
${settings.localRepository}表示本地仓库的地址;
5.Java系统属性
(所有的Java系统属性都可以使用Maven属性引用)
使用mvn help:system命令可查看所有的Java系统属性;
System.getProperties()可得到所有的Java属性;
${user.home}表示用户目录;
6.环境变量属性
(所有的环境变量都可以用以env.开头的Maven属性引用)
使用mvn help:system命令可查看所有环境变量;
${env.JAVA_HOME}表示JAVA_HOME环境变量的值;
4.2 资源过滤
maven-resources-plugin的默认行为是将项目主资源文件复制到主代码编译输出目录中,将测试资源文件复制到测试代码编译输出目录中,如果开启了资源过滤,那么可以读取资源目录下的文件内容,即解析资源文件中的maven属性。
如果是web资源,则是通过maven-resources-plugin处理。
4.3 profile
可以根据环境不同选择不同的资源配置,<activeByDefault>表示默认激活的环境配置资源。
<profiles>
<profile>
<id>local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<conf-dir>local</conf-dir>
</properties>
</profile>
<profile>
<id>dev</id>
<properties>
<conf-dir>dev</conf-dir>
</properties>
</profile>
<profile>
<id>beta</id>
<properties>
<conf-dir>beta</conf-dir>
</properties>
</profile>
<profile>
<id>miniflow</id>
<properties>
<conf-dir>miniflow</conf-dir>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<conf-dir>test</conf-dir>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<conf-dir>prod</conf-dir>
</properties>
</profile>
<profile>
<id>staging</id>
<properties>
<conf-dir>staging</conf-dir>
</properties>
</profile>
</profiles>
profiles
可以通过命令行参数 -P 加上profile的id来激活profile,多个id之间用逗号分隔。
settings.xml文件中也会有profile的配置,如果一个settings.xml中的profile被激活,它的值会覆盖任何其它定义在pom.xml中带有相同id的profile。
maven全局配置文件settings.xml详解 @静默空虚
5 超级POM
Maven约定大约配置,在$MAVEN_HONE/lib/maven-model-builder-x.x.x.jar中的org/apache/maven/model/pom-4.0.0.xml路径下存在超级pom。每个Maven项目都会继承这个超级pom,类似java中的object类,
超级pom声明了仓库等信息。
网友评论