maven在平常工作中使用很多,但大多数时候都是copy and change pom.xml,内部的配置理解不够,再遇到打包,依赖问题每次都很头疼,本文就陆续的整理工作中遇到常见的问题,希望能够避免重复采坑,并能沉淀对maven打包工具的理解
maven 命令
mvn dependency:tree 查看maven依赖树
mvn dependency:resolve 查看最终maven依赖的jar包,但是这个不会考虑例如shade插件的黑白名单排掉的包
# 命令行跳过常规的检查,也可以通过profile管理,打包时指定profile,profile中指定pluginManagement,参照flink父pom指定的
maven clean package -Denforcer.skip=true -Dmaven.test.skip=true -DskipTests -Drat.skip=true -Dcheckstyle.skip=true -Dscalastyle.skip=true
# 查看某个子module最终的打包pom
mvn help:effective-pom
<profile>
<id>fast</id>
<activation>
<property>
<name>fast</name>
</property>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.rat</groupId>
<artifactId>apache-rat-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.scalastyle</groupId>
<artifactId>scalastyle-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>com.github.siom79.japicmp</groupId>
<artifactId>japicmp-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
然后在打包时指定profile
mvn clean package -DskipTests -Dfast
# 也可以通过
mvn clean package -DskipTests -Pfast
一种是直接通过-P指定profile,一种是通过环境变量等于specific value时激活。具体可以参看:profile指定策略:https://maven.apache.org/guides/introduction/introduction-to-profiles.html
maven shade plugin
maven shade build插件通常用来管理冲突,目前用的比较多的功能是黑名单和白名单,以及relocation功能
黑白名单机制
artifactSet标签 可以通过include和exclude来进行白名单和黑名单的控制,artifact级别的(maven包级别);顺序是白名单先生效,黑名单再生效,如果没有白名单,默认包括全部。如果设置了白名单的话,那么只有白名单中指定的jar才会保留。filters标签可以进行更细粒度的控制,可以再单个artifact内,进行include和exclude的控制,是文件级别的黑名单和白名单,artifact可以使用通配符号。生效顺序是artifactSet和filter的白名单,再进行黑名单排除,但是通过filter指定的文件,是不受影响的,始终保留。可以在mvn打包命令执行时查看最终include和exclude的类有哪些。
参考:
https://maven.apache.org/plugins/maven-shade-plugin/examples/includes-excludes.html
https://shalk.xyz/post/maven-shade-plugin-usage/
mvn依赖传递性:https://blog.csdn.net/tojohnonly/article/details/79101841
注意:
在代码中引入一个第三方依赖的时候最好通过mvn dependency:tree 查看下会引入哪些具体的三方依赖, 常见的三方框架包为了避免冲突,要趁早relocation掉
plugin配置和父pom中配置项merge策略
假设父亲的plugin有如下的配置项
<configuration>
<items>
<item>parent-1</item>
<item>parent-2</item>
</items>
<properties>
<parentKey>parent</parentKey>
</properties>
</configuration>
而子module对同一个插件有如下的配置项
<configuration>
<items>
<item>child-1</item>
</items>
<properties>
<childKey>child</childKey>
</properties>
</configuration>
通过以下命令,查看最终的有效pom如下
mvn help:effective-pom
<configuration>
<items>
<item>child-1</item>
</items>
<properties>
<childKey>child</childKey>
<parentKey>parent</parentKey>
</properties>
</configuration>
可以看到默认的merge策略是遍历element name,父module中的元素只有在子module中没有的时候才会被append到子module中,merge的过程只是根据element name来进行。
如果子module指定成如下的形式
<configuration>
<items combine.children="append">
<!-- combine.children="merge" is the default -->
<item>child-1</item>
</items>
<properties combine.self="override">
<!-- combine.self="merge" is the default -->
<childKey>child</childKey>
</properties>
</configuration>
生成的有效文件如下
<configuration>
<items combine.children="append">
<item>parent-1</item>
<item>parent-2</item>
<item>child-1</item>
</items>
<properties combine.self="override">
<childKey>child</childKey>
</properties>
</configuration>
可以注意到和默认行为(merge)不同,append会将父module的element都追加上来,不管子module中是否存在,override则忽略父module的相应element的配置项。
使用是还需要注意以下几点
- 这个属性只针对声明的element生效,如上面xml中只会对items和properties下的第一层元素生效,如果item还有下集元素,将应用默认的merge策略
- combine.* 这些属性也会集成,如果在父module中添加此属性,子module都会直接继承,除非子module单独指定这个属性
- 以上的config merge策略,只是针对plugin的配置项,对pom中的其他元素并没有效果
参考: https://blog.sonatype.com/2011/01/maven-how-to-merging-plugin-configuration-in-complex-projects/
maven bom
https://stackoverflow.com/questions/41816411/why-the-maven-child-referencing-versions-from-bom-does-not-work
http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
https://blog.csdn.net/lonelymanontheway/article/details/80623408
maven的生命周期
maven goal可以不和build phase绑定,单独执行 http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Built-in_Lifecycle_Bindings
一个build phase可以有一个或多个goal,依次执行,一个goal可以属于多个phase,那么会被执行多次
mvn clean dependency:copy-dependencies package
clean 和 package都是一个phase,而dependency:copy-dependencies是某个插件的goal,这样的执行顺序就是clean-> dependency:copy-dependencies -> package