Maven Profile动态替换web.xml参数

最近项目中需要引入一个叫做ABTest工具。看了一下官方给出的文档,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- abtest 配置 -->
<filter>
<filter-name>AbtestFilter</filter-name>
<filter-class>com.******************.*********.web.DefaultTestFilter</filter-class>
<init-param>
<param-name>env</param-name>
<param-value>${env}</param-value>
</init-param>
<init-param>
<param-name>appName</param-name>
<param-value>demo</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>AbtestFilter</filter-name>
<url-pattern>*.htm</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>AbtestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- abtest 配置结束 -->

可以看到其中${env}的变量值是需要进行动态替换的。一开始我觉得可以使用maven-war-plugin来完成这个配置,BUT NOT WORK FOR ME!绕了好久的弯,终于看到了项目中进行config.properties替换使用的一个插件maven-antrun-plugin,BINGO,替换成功!

先进行一下说明,项目中并没有使用antx来进行配置,因此适用于antx的方案不一定适合本项目,所以一开始就没有往antx的方向考虑。

使用maven-war-plugin进行替换[❌]

看了一下父pom的配置,发现它使用了profile进行多套环境的参数替换,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!-- 预发布环境 -->
<profile>
<id>staging</id>
<properties>
<env>staging</env>
<ant-properties-path>src/main/resources/conf/config-staging.properties</ant-properties-path>
</properties>
</profile>
<profile>
<id>publish</id>
<properties>
<env>publish</env>
<ant-properties-path>src/main/resources/conf/config-pro.properties</ant-properties-path>
</properties>
</profile>
<!-- 生产环境 -->
<profile>
<id>production</id>
<properties>
<env>production</env>
<ant-properties-path>src/main/resources/conf/config-pro.properties</ant-properties-path>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>

可以看到不同的环境有不同的配置文件。在profile中添加一个属性test-env,如下:

1
2
3
4
5
6
7
8
9
10
11
12
<!-- 生产环境 -->
<profile>
<id>production</id>
<properties>
<env>production</env>
<test-env>online</test-env>
<ant-properties-path>src/main/resources/conf/config-pro.properties</ant-properties-path>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>

然后再在webapp子pom中进行maven-war-plugin插件的配置,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>${basedir}/src/main/webapp</directory>
<excludes>
<exclude>**/.svn</exclude>
</excludes>
<includes>
<include>**/web.xml</include>
</includes>
</resource>
</webResources>
<webXml>${basedir}/src/main/webapp/WEB-INF/web.xml</webXml>
<warSourceDirectory>${basedir}/src/main/webapp</warSourceDirectory>
</configuration>
</plugin>

然后使用maven命令进行构建,mvn clean package -Dmaven.test.skip=true -Pproduction,但是生成war包以后,进入WEB-INF目录一看,发现这个根本就没有进行替换。NOT WORK FOR ME!

说明这个方法我觉得理论上应该是可以的,如果有更好的建议或者我的描述有不对的地方欢迎指出来哈!非常感谢!

使用maven-antrun-plugin进行替换[✔️]

后面研究了一下config.properties是如何实现多套环境的替换的,终于在同一个文件,也就是webapp子pom里面找到了答案,它使用了maven-antrun-plugin进行运行时构建,具体的替换逻辑如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>configReplace</id>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<copy file="${ant-properties-path}"
tofile="${project.build.directory}/classes/config.properties" />
</tasks>
</configuration>
</execution>
</executions>
</plugin>

进入查看tasks标签的描述,如下:

1
2
3
4
5
6
7
8
9
<parameter>
<name>tasks</name>
<type>org.apache.tools.ant.Target</type>
<required>false</required>
<editable>true</editable>
<description>The XML for the Ant task. You can add anything you can add
between &amp;lt;target&amp;gt; and &amp;lt;/target&amp;gt; in a build.xml.
</description>
</parameter>

具体的意思是说我们可以在build.xml文件中的<target>标签内添加任何任务。我找了一下build.xml的基本demo,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8" ?>
<project name="AntTestDemo" default="run" basedir=".">
<property name="src" value="src"/>
<property name="dest" value="classes"/>
<property name="helloant_jar" value="helloant.jar"/>
<target name="init">
<mkdir dir="${dest}"/>
</target>
<target name="compile" depends="init">
<javac srcdir="${src}" destdir="${dest}"/>
</target>
<target name="build" depends="compile">
<jar jarfile="${helloant_jar}" basedir="${dest}"/>
</target>
<target name="run" depends="build">
<java classname="com.zdz.ant.test.HelloAnt" classpath="${helloant_jar}"/>
</target>
<target name="clean">
<delete dir="${dest}" />
<delete file="${helloant_jar}" />
</target>
<target name="rerun" depends="clean,run">
<ant target="clean" />
<ant target="run" />
</target>
</project>

我发现这些target下面的标签不正是一些常见的命令吗?这个太强大了!因此,我想到可不可以使用一个替换命令,直接使用profile中定义的属性直接进行web.xml中的属性替换。上网一查,果然有同学这样做过,BINGO!我果断在webapp子pom中添加一个execution任务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<execution>
<id>envReplace</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<replace file="${project.build.directory}/demo/WEB-INF/web.xml"
token="defaultTestEnv"
value="${test-env}"/>
</tasks>
</configuration>
</execution>

web.xml文件中要替换的地方如下:

1
2
3
4
5
6
7
8
9
10
11
12
<filter>
<filter-name>teslaFilter</filter-name>
<filter-class>com.******************.*********.web.DefaultTestFilter</filter-class>
<init-param>
<param-name>env</param-name>
<param-value>defaultTestEnv</param-value>
</init-param>
<init-param>
<param-name>appName</param-name>
<param-value>demo</param-value>
</init-param>
</filter>

然后再重新打包,果然OK了。

总结

这个动态替换的问题确实会困扰到很多同学,至少困扰了我半个下午来解决这个问题,在这里记录一下,和大家分享这个问题的一种解决思路。

分享到