Maven占位符、定界符

一、缘起

在前面写了一篇《Maven打包SpringBoot项目,排除第三方依赖包》,写的过程中,又再次与maven占位符这个问题重逢了。说到重逢,是因为在很早之前,我刚搭建spring boot项目的时候,就栽在这个坑里了。那是只是浅显的知道spring boot 偷偷摸摸地把maven的默认占位符给修改了,但是,没有去深入的理解。现在,回过头来,梳理一遍。

二、运行环境

操作系统:Windows 10 ;
开发工具:IDEA-2019.3;
Web服务器:Tomcat 9.0.24;
JDK版本: jdk 1.8.0_221;
Maven版本:apache-maven-3.6.1
Spring boot 版本:2.0.9.RELEASE

三、原理分析

工欲善其事,必先利其器。想要把功能做好,就要先明白背后的原理。原理理解清楚了,实际操作可谓是手到擒来。
说到maven的占位符,其实并不准确。这也是一直让我混淆的概念。
我们分开来讲:

  1. maven中有很多内置变量,具体有哪些变量,可以参考https://www.jianshu.com/p/ded7dfa2c3d8。比如,basedir表示项目根目录,version表示项目版本。而这些变量如何使用呢,就是使用占位符了,如${version}。这里的占位符就是${ }。这里是maven默认的,而这个占位符使用的场景,也就是在pom.xml之中。这里的占位符,我几乎没有见过要去修改的。
  2. 而通常意义上说的,其实是maven的 maven-resources-plugin插件中的一个配置项${resource.delimiter}。翻译过来,是定界符的意思。中文互联网太多以讹传讹和一知半解了。那么,这个只是一个小小插件的配置项,为何就上升到了好像成了一个maven的一个配置呢?
    首先,就是这个定界符和上面的变量占位符长的一毛一样,这不就是故意让人混淆的嘛;其次,还要从 maven-resources-plugin这个插件本身的功能和特别之处说起了。
    Resources插件负责处理项目资源文件并拷贝到输出目录。Maven将main resources和test resources分开,一般main resources关联main source code,而test resources关联test source code。
    这有啥特殊的呢?看一下官方的这句话:

Starting with version 2.3 this plugin uses the Maven Filtering shared component for filtering resources.

就是说呢,从2.3版本开始,resources插件可以实现过滤资源了。这里过滤的名称起的不好,其实,可以说预编译,或者是替换。就是把定界符里的变量用真实的值替换掉。
这里定界符一般定义在src/main/resources目录下的文件中,而真实的值可以是maven内置变量,中定义的变量,或者是过滤器中引用的文件中的变量值。这里是否启用过滤功能,也是可以配置的。说这么多有啥用呢?这个主要就是用在项目多环境配置中。

五、总结

寻找资料,来来回回还都是官方文档是最权威的。本身基础不牢固,就要把基础打牢靠才可以。

六、附录

  1. maven resources插件官方地址:http://maven.apache.org/plugins/maven-resources-plugin/index.html
  2. maven filter功能官方地址:http://maven.apache.org/shared/maven-filtering/
  3. maven 父子模块的插件传递机制
    maven子模块可以通过继承获得的pom中元素有:
  • properties:自定义的Maven属性
  • dependencyManagement:项目的依赖管理配置
  • build:包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等
  1. maven 中的resoures插件
    resoures插件,是maven默认绑定的插件,所以,不用显式的引入。这里还是我的知识盲点,到底是如何引入的,我还没有弄清楚。
  2. spring boot 中 定界符的配置
    官方文档:“How-to” Guides => 2. Properties and Configuration => 2.1.1. Automatic Property Expansion Using Maven:

If you inherit from the spring-boot-starter-parent POM, the default filter token of the maven-resources-plugins has been changed from ${*} to @ (that is, @maven.token@ instead of ${maven.token}) to prevent conflicts with Spring-style placeholders. If you have enabled Maven filtering for the application.properties directly, you may want to also change the default filter token to use other delimiters.

上面是官方的文档。大概意思就是说,因为maven的定界符和spring自身的属性配置的占位符冲突了,所以,spring boot中把maven的定界符改成了@,而spring自己还是使用${}。

  1. 父(Super)POM

父(Super)POM是 Maven 默认的 POM。所有的 POM 都继承自一个父 POM(无论是否显式定义了这个父 POM)。父 POM 包含了一些可以被继承的默认设置。因此,当 Maven 发现需要下载 POM 中的 依赖时,它会到 Super POM 中配置的默认仓库 http://repo1.maven.org/maven2 去下载。
Maven 使用 effective pom(Super pom 加上工程自己的配置)来执行相关的目标,它帮助开发者在 pom.xml 中做尽可能少的配置,当然这些配置可以被重写。
使用以下命令来查看 Super POM 默认配置:
mvn help:effective-pom

上面这段话,是我摘抄自https://www.runoob.com/maven/maven-pom.html的,因为说的太好了。完美解释了maven构建的底层逻辑和思想。给我解了惑。
但是上面去默认仓库下载的路径是打不开的。我找了一下,可以在这个路径找到:http://maven.apache.org/ref/3.0.4/maven-model-builder/super-pom.html

  1. Maven的几个核心概念
    生命周期(lifecycle):maven将构建项目的过程进行了抽象,抽象出来了一个过程,这个过程被称作生命周期(lifecycle)。lifecycle是有多个有序的阶段(phase)构成的。
    阶段(phase):maven将lifecycle划分为多个有序的过程(step),每一个过程被称作一个阶段(phase)。
    目标(goal):goal在maven中是真正执行任务的单元,goal的提供者是插件(plugin),每一个plugin可能提供多个goals。例如 mvn compiler:compile表示了一个goal,其提供者是插件 compiler。compiler其实是这个插件的缩写,其完整的插件名字为org.apache.maven.plugins:maven-compiler-plugin,compile仅仅是这个一个插件中的一个goal。
    三者之间的管理:goal是一个执行任务的最小单元,每一个goal都是由其对应的plugin提供的;可以将对应的goal绑定到某个phase上,当在进行maven构建的过程中只要执行到了对应的phase上,就可以在当前phase上完成goal的执行。

你可能感兴趣的:(Maven占位符、定界符)