一个项目应对各式各样环境-profile完美应付 | 再也不要每套环境改次配置了

3,561 阅读5分钟

本文正在参加「金石计划 . 瓜分6万现金大奖」

前言

  • 一个项目能够正常上线需要经历各种环境的测试洗礼。面对如此多的环境我们在打包的时候也很头疼,好在 maven能够帮助我们巧妙的进行携带设置。达到不同环境设置不同的环境参数。
  • maven 中提供 profiles 支持我们多环境配置。 profiles 又分为系统配置和全局配置。所谓系统配置就是在项目的 pom.xml 中进行配置,仅对当前项目有效。而全局配置就是在 mavensettings.xml 中配置,当maven所有项目有效。

profiles配置

  • 这里谈论的是项目中进行配置说明了。首先在 profiles 中支持配置多个 profile , 每个 profile 除了存在一个证明环境唯一ID的 id属性外,还可以存在 pom.xml 中其他正常的标签。比如你可以在 profile 中放置 dependencies 来通过环境控制依赖包的引入与否。 比如你可以通过 profile 中放置 properties 来配置 pom.xml 中参数配置。

指明环境

  • 当我们系统中配置了很多个 profile 的时候而又没有设置自动激活,这个时候我们在打包的时候就需要手动设置激活选项了。 mvn clean intsall -Pprofile1,profile2 , 这个命令说明我们选择 profile1profile2 两套环境里的配置和主配置结合进行打包。

默认生效

  • 相比较与指明道姓的激活方式,默认激活就显得格外的方便了。比如公司里有 jdk8 的项目也有 jdk11 的项目。这种情况我们每次在打包的时候再去指定激活就显得不合适了,因为当前 java 版本 maven 是能够获取到的,这时候我们手动激活显得有点鸡肋了。还有些是未来可能会改动或者改动的频率不是很大,这时候就更适合默认激活了。
<profile>  
  <id>dev</id>  
  <activation>  
    <activeByDefault>true</activeByDefault>  
  </activation>  
  ...  
</profile>  
  • settings.xml 配置文件中除了上方在每个 profile 中选择是否默认激活以外,还可以在最后统一选择激活
<settings>  
  ...  
  <activeProfiles>  
    <activeProfile>local_db</activeProfile>  
  </activeProfiles>  
</settings>  

依赖文件

  • 比如我们公司项目 jar 都是经过加密的,我们本地都是存在密钥的。我们的加密组也为我们提供了加密程序。加密程序依赖于一份密码本。这个时候我们打包的时候就可以通过判断是否存在密码本而选择是否加载加密程序的 jar
  • 还有的时候我们需要判断不存在某个文件的时候在执行某些操作。这些 profile 都是可以帮助我们实现的。
  • 这里的文件路径经过测试时相对于 pom.xml 的相对位置。你也可以填写 绝对路径。(仅在linux上进行了测试 , 且这里的绝对路径不能 ~/temp/xxxx , 必须写 /home/zxhtom/temp/xxxx)

存在文件

<profile>  
  <id>dev</id>  
  <activation>  
    <activeByDefault>false</activeByDefault>  
    <file>  
      <exists>file2.properties</exists>  
    </file>  
  </activation>  
  ...  
</profile>  

不存在文件

<profile>  
  <id>dev</id>  
  <activation>  
    <activeByDefault>false</activeByDefault>  
    <file>  
      <missing>file2.properties</missing>  
    </file>  
  </activation>  
  ...  
</profile>  

依赖系统参数

  • 上面通过文件进行判断在某种场景下显得还是不智能。 比如我现在有一个包 默认需要加载进来, 但是我想动态控制它是否加载。如果通过默认的话那么后续我就无法更改,如果通过文件进行控制,那么每次我还得新增删除文件来达到控制的效果。那么有没有类似于 -P 的属性来动态控制加载呢?注意这个场景和 -P 不同的是
  • -P 是默认不加载 ,指定了就加载
  • 而我要的是 默认加载 , 指定了不加载 。 恰好跟他是相反的效果
  • 经过我翻阅资料,终于发现有这个参数可以控制,就是 property这个参数控制,这个属性用来判断系统参数。
  • 这个系统参数你可能有些陌生了,实际上我们经常使用 , 在打包的 时候 mvn clean install -Dhello=zxhtom 这个命令就指定了一个系统变量名叫 hello。值为 zxhtom 。这样我们在 pom.xml 就能够进行判断了。

系统参数匹配

  • 当存在系统变量 hello=zxhtom 时激活
<profile>  
  <id>dev</id>  
  <activation>  
    <activeByDefault>false</activeByDefault>
    <property>  
      <name>hello</name>  
      <value>zxhtom</value>  
    </property>
  </activation>  
  ...  
</profile>  
  • 当存在系统变量 hello 时激活
<profile>  
  <id>dev</id>  
  <activation>  
    <activeByDefault>false</activeByDefault>
    <property>  
      <name>hello</name>  
    </property>
  </activation>  
  ...  
</profile>  

系统参数取反

  • 上面好像还是没法做到 默认引入依赖,通过参数动态控制依赖的效果。别着急 我们还有一个取反的功能。
<profile>  
  <id>dev</id>  
  <activation>  
    <activeByDefault>false</activeByDefault>
    <property>  
      <name>!hello</name>  
    </property>
  </activation>  
  ...  
</profile>  
  • 有了上面配置我们默认不存在hello 这个系统变量。则默认 dev 的 就会生效。 mvn clean intall -Dhello 这样 dev 就不会生效了。
  • 除了 maven 打包时候需要指定参数, 有的时候我们在 idea 中运行的时候也需要设置 java -jar -Xmx2512M -Xms2512M -Dhello 诸如这样就可以了。

依赖系统

  • 上面是我们依赖自定义设置决定 profile 的生效与否。我们还可以依赖具体的环境参数
<profile>  
  <id>dev</id>  
  <activation>  
    <activeByDefault>false</activeByDefault>  
    <os>  
      <name>Windows XP</name>  
      <family>Windows</family>  
      <arch>x86</arch>  
      <version>5.1.2600</version>  
    </os>  
  </activation>  
  ...  
</profile>  

依赖JDK

  • 还有就是我们开头说到的,根据不同的java版本生效不同的配置
<profile>  
  <id>dev</id>  
  <activation>  
    <activeByDefault>false</activeByDefault>  
    <jdk>11</jdk>   
  </activation>  
  ...  
</profile>  

全局与局部冲突

  • -P 可以指定多个参数的 -P dev release 就可以了。而对于pom和setting,两者是覆盖合并关系, 当指定 -P 后 会从 pom.xml 中查找 profile,然后从 settings 中 查找 profile,合并后作为最终 profile, 相同项 pom.xml 会覆盖 settings
  • 总结下来就是局部的会覆盖全局的。
  • settings.xml中的profile和pom中的profile的区别:settings.xml中的profile只有activation,repositories,plugineReositories,properties四个子元素。通常是用来配置仓库信息的。

本文正在参加「金石计划 . 瓜分6万现金大奖」