想让某个profile“根据项目的配置自动激活”,无奈试过各种方法、策略,都不行。
下面是一个profile的标准配置:
<profiles> <profile> <id>exe-jar</id> <activation> <property> <name>JAR-BOOT</name> </property> <file> <exists>${basedir}/src/main/resources/META-INF/jar.app</exists> <exists>profiles.xml</exists> </file> </activation>
首先,根据官方文档:
https://maven.apache.org/settings.html#Profiles
摘录如下:
Activation occurs when all specified criteria have been met, though not all are required at once.
jdk:
activation
has a built in, Java-centric check in thejdk
element. This will activate if the test is run under a jdk version number that matches the prefix given. In the above example,1.5.0_06
will match. Ranges are also supported. See the maven-enforcer-plugin for more details about supported ranges.os: The
os
element can define some operating system specific properties shown above. See the maven-enforcer-plugin for more details about OS values.property: The
profile
will activate if Maven detects a property (a value which can be dereferenced within the POM by${name}
) of the correspondingname=value
pair.file: Finally, a given filename may activate the
profile
by theexistence
of a file, or if it ismissing
.
The activation
element is not the only way that a profile
may be activated. The settings.xml
file’s activeProfile
element may contain the profile’s id
. They may also be activated explicitly through the command line via a comma separated list after the -P
flag (e.g. -P test
).
To see which profile will activate in a certain build, use the maven-help-plugin
.
mvn help:active-profiles
profile的自动激活方式有4种。因为我是想根据项目配置来自动激活,上面这几种方式均不能达到效果。
根据jdk、os激活,不是我想要的,pass。
根据property激活,这个有点坑,只能是系统变量才行。mavan pom.xml里面定义的properties无法识别。
所以,这四种方式都很鸡肋,都无法做到根据项目来自动激活。
我找到了作者说的一句话:
Profile activgation is the first step of the first phase
and profile activation does not work with POM property but with CLI property
因为系统变量,需要在打包命令,或者环境变量中设置。所以这种方法对我来说不可取(因为我想根据项目自身配置自动激活,不需要人为配置)。
最后抱了一丝希望:根据file激活,这个也很坑。参见这个issues:
https://issues.apache.org/jira/browse/MNG-2363(我的需求跟这个描述一模一样!!)
这个file的路径,如果是相对路径,且是在父pom.xml中设置的profiles,则file路径是针对于父pom.xml项目构建路径的绝对值。例如 profiles.xml 或 ${basedir}/profiles.xml,都是指向的父pom.xml构建时的路径,例如:D:\__SYNC2\git\jretty-pom\profiles.xml,亲测如此。这样子项目中的profiles.xml文件就不会起作用。垃圾垃圾!怎么会这样?这应该是bug吧!总之,file激活太不靠谱。
引申结论
由于这个问题,又对Maven进行了各方面的研究,对Maven的理解也加深了。
总结出一点:Maven不太适合多模块的复杂项目(可能大多数人的项目都不会复杂到我说的那种程度,后面有举例)。具体说起来很复杂,我简单提几点(不做详细阐述)
1、新版Maven提供了 <scope>import</scope>,但是仅能引入 dependency组件。至于其他标签都无法继承,例如build标签里面的那些,以及properties标签。这个缺点对结构复杂、继承模块非常多的项目来说很严重,就拿build标签里面的东西来说,多继承也是相当有必要的。
2、尝试用profile来解决pom.xml的多继承问题,倒是可以包含build、properties等标签,但是由于上文所述的问题,这种profile切换的功能十分鸡肋(不能根据项目的变量动态切换),它只能通过jdk、cli参数、系统变量来切换————对于多模块项目来说,并不是每个模块的build、properties配置都是一样的,有些是jar、有些是war,而通过cli参数、系统变量,只能针对单个项目去控制变量才能实现,对于多模块项目,没办法单独为每个模块指定cli参数(mvn -P参数对多模块的所有子模块生效,无法单独指定某个子模块生效,除非逐个项目执行构建,所以我说Maven适合单项目,不适合多模块项目的构建,另外当初Ant流行就是因为Ant对项目的构建更灵活,弥补了Maven的缺陷)。实际案例有很多(例如上文提到的https://issues.apache.org/jira/browse/MNG-2363案例)。所以,放弃profile。
3、既然profile无法解决pom.xml继承的问题,那么只能退而求其次,使用module-parent的项目结构,使用parent-children来实现一定程度的继承。
举个例子,我的项目比较复杂,改造前如下(简化结构):
talos-parent talos-api talos-common talos-app1 talos-app2 himes-parent himes-api himes-common himes-app1 himes-app2
由于talos-app1、talos-app2、himes-app1……等几十个项目的pom.xml几乎是一模一样的,于是想通过继承的方式将pom.xml集中管理起来。改造后如下:
talos-parent talos-api talos-common talos-app-parent talos-app1 talos-app2
这样一来,talos-app1和talos-app2的配置就可以继承 talos-app-parent,从而自身简化到只有一个引用声明:
<project> <artifactId>talos-app1</artifactId> <parent> <groupId>com.fbank</groupId> <artifactId>talos-app-parent</artifactId> <version>1.0.0-SNAPSHOT</version> </parent> </project>
但是,很显然,talos-app-parent的作用范围仅限于 其子module,对于himes-app1、himes-app2等其他项目无能为力。
然而这并不是我期望的,talos-app和himes-app仅仅是项目不同,pom.xml其实大同小异,不能继承、非常遗憾!!(Maven的对手Gradle可以做到,它可以将片段传到远程仓库,供其他项目可以include引入)
3、Maven有几个命令可以控制 module子项目的打包,但是不支持子项目嵌套。例如上面的双parent项目结构,mvn install可以一键打包所以模块。但是mvn -pl -am这些命令参数,只能对一级模块起作用,无法控制内层的二级、三级子模块项目,而复杂的项目有二级、三级子模块很正常。
4、像Spring这样复杂的项目群,没有采用Maven来管理,看来是明智的。
5、我曾经研究对比过Maven和Gradle,只能说Gradle更强大、更灵活,但是也更复杂和不可控,是一把双刃剑。
结论:
如果是小团队独立项目,能忍受多个项目的Maven pom.xml内有上百行的重复,那用maven没问题。
如果是大范围的很多项目、涉及几十上百开发人员,且需要统一管理,那么用Gradle是最方便的,但是由于很多团队不会用Gradle,要推广实施并不容易。