在springboot或传统springmvc的tomcat项目中,为了实现spring容器文件中的变量替换,我们通常可以在项目的resource目录下新建几个环境目录,例如rd、test、dev、stress、online等等,然后再在对应的环境目录下放一些数据库的配置文件(例如jdbc.properties)、redis的配置文件(例如redis.properties)等等,当然你也可以直接使用一个config.properties(里面包含了数据库和redis以及其他的变量定义)。这样做了以后,在pom.xml中的profile标签中,把你上述定义的几个环境目录也在profile标签中定义出来,并选择其中一个作为默认激活选项。当使用maven打包并使用-P命令指定环境时,就会打包对应环境下的配置,并自动进行变量替换。

      以上是常规做法,但是当你在webapp/WEB-INF/web.xml和webapp/META-INF/context.xml这两个文件中也那么做的时候,发现最后打包完占位符依然是占位符,并没有自动替换,这是为什么呢?

      要实现webapp/WEB-INF/web.xml和webapp/META-INF/context.xml这两个文件中的占位符(或EL表达式)自动变量替换,就要借助maven的一个插件-----maven-war-plugin,有了这个插件,web项目文件的任何变量几乎都可以替换。

      一、下面先从webapp/WEB-INF/web.xml如何实现变量替换说起:

      ①因为我的项目使用了单点登录,那么就要在web.xml中配置casServer、casServerUrlPrefix、serverName这几个参数。之前在web.xml中的filter中写的是具体值,导致每个环境都要改一遍,现在我把他们用占位符代替,如下所示:

maven archetype 不替换 maven 打包 替换变量_maven archetype 不替换

maven archetype 不替换 maven 打包 替换变量_maven_02

②然后在pom.xml中的profile中定义这几个参数的具体值,并且每个环境的具体值和每个环境的profile定义在一起,这里以test环境为例,其他环境profile形式相同(值不同),如下所示:

maven archetype 不替换 maven 打包 替换变量_plugin_03

  ③最后是maven-war-plugin的配置,如下:

maven archetype 不替换 maven 打包 替换变量_maven_04

    ④最后用maven编译,发现变量全部替换成功,不过这里有一点需要注意的地方就是maven-war-plugin插件对字符编码的支持不太好,如果你的web.xml文件中包含中文字符(包括变量值和中文注释),那么maven编译完就会中文乱码,导致服务无法启动,报如下错误:

maven archetype 不替换 maven 打包 替换变量_web app_05

    这个解决方法就是:一是去掉web.xml中的中文字符;二是将web.xml中的第一行scheme头中的字符编码声明为GBK,如下:

maven archetype 不替换 maven 打包 替换变量_plugin_06

 

     二、下面我们来看下webapp/META-INF/context.xml如何实现变量替换

     ①我的项目中使用了基于tomcat的JNDI数据源,你可以在tomcat的conf目录下的server.xml中新建一个resource标签配置jdbc连接,也可以在 项目webapp/META-INF/目录下的context.xml中定义resource标签来配置jdbc连接,当这两个地方同时配置时,webapp/META-INF/context.xml会覆盖tomcat的conf目录下的server.xml中的配置。所以如果想在webapp/META-INF/context.xml中实现变量替换,先将context.xml中的jdbc连接地址、用户名、密码用占位符代替,然后有两种方式实现maven打包自动替换,都要借助maven-war-plugin插件:

     第一种方式就是上面的web.xml方式,先在pom.xml中的对应环境的profile标签中定义jdbc的连接地址、用户名和密码的具体值,然后在maven-war-plugin中指定资源目录和要过滤的文件以及打包的目标目录。这里我们来着重介绍

     第二种方法:

      ②在resource目录下的rd、test、dev等目录下分别建一个context.xml文件,文件里面分别是各自环境对应的jndi配置。我们的目的是在maven编译完打包后实现webapp/META-INF/目录下context.xml文件的替换。

      ③接下来配置maven-war-plugin打包方式,如下:

maven archetype 不替换 maven 打包 替换变量_jndi_07

    ④maven编译打包完,发现成功替换;从这个方法来看,其实上面的web.xml也可以采用这种方式,在rd、test等目录下分别建一个web.xml,每个文件中分别是各自环境中的casServer地址等等,然后配置maven-war-plugin打包方式。不过这种方式的缺点就是新建的文件太多了,显得臃肿

     参考地址:

http://maven.40175.n5.nabble.com/How-to-filter-META-INF-context-xml-td120983.html

http://maven.apache.org/plugins/maven-war-plugin/examples/adding-filtering-webresources.html