我有一个Java webapp项目,我在Eclipse中开发(更准确地说是MyEclipse 10)并使用Maven 3构建。
我有以下布局(仅包括与我的问题相关的文件:
project root
|-- src
| |-- main
| | |-- java
| | |-- resources
| | | |-- log4j.xml
| | | +-- struts.properties
| | |-- webapp
| | | |-- META-INF
| | | | +--context.xml
| | |-- config
| | | |-- test
| | | | |--log4j.xml
| | | | |--struts.properties
| | | | +--context.xml
| | | +-- prod
| | | | |--log4j.xml
| | | | |--struts.properties
| | | | +--context.xml
| +--test
+--pom.xml
如您所见,我包含了许多配置文件。在项目结构中处于适当位置的人,即src/main/resources
和src/main/webapp
内部,是我在MyEclipse工作时经常使用的那个。我可以使用MyEclipse连接器自动将部署更新到例如我的开发机器上的Tomcat实例。我只需点击“运行服务器”即可调试。实际上,在这种情况下根本不需要使用Maven。
然后,当我想为测试或生产等其他环境构建版本时,我运行mvn -P test clean install
并构建一个很好的WAR。
我的目标是用src/config/{environment}/
中的那些替换最终WAR中的配置文件。
我在pom.xml
:
<profiles>
<profile>
<id>test</id>
<properties>
<environment>test</environment>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<environment>prod</environment>
</properties>
</profile>
</profiles>
然后,我尝试将这些资源从指定的配置文件(使用environment
变量)复制到WAR内部的正确位置(或将压缩到WAR中的临时文件夹):
<webResources>
<resource>
<directory>/src/main/config/${environment}</directory>
<targetPath>META-INF/</targetPath>
<includes>
<include>context.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/config/${environment}</directory>
<targetPath>WEB-INF/classes/</targetPath>
<includes>
<include>
struts.properties
</include>
<include>
log4j.xml
</include>
</includes>
</resource>
</webResources>
现在这似乎有效,除了“标准”资源被复制到此后的目录,因此它们会覆盖这些文件。所以我总是最终得到来自log4j.xml
的{{1}}而不是来自src/main/resources
src/main/configuration/prod/
从Maven输出中提取:
[INFO] Processing war project
[INFO] Copying webapp webResources [D:\workspace\MyProject/src/main/config/prod] to [D:\workspaces\SITEL\Webfauna\target\Webfauna]
[INFO] Copying webapp webResources [D:\workspace\MyProject\src/main/config/prod] to [D:\workspaces\SITEL\Webfauna\target\Webfauna]
[INFO] Copying webapp resources [D:\workspace\MyProject\src\main\webapp]
正如您在最后一行所看到的那样,来自src/main/webapp
的内容会在以后复制,从而覆盖我的自定义文件:(
我的问题:如何强制Maven使用“来自激活的配置文件”的文件并以某种方式覆盖“自然”文件?
答案 0 :(得分:12)
正如第二个{{3}}所指出的,最简单的解决方案是过滤掉原始文件,以便它们可以被配置文件文件夹中的文件替换。
所以我添加了对标准资源的过滤:
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<!-- Exclude those since they are copied from the profile folder for the build -->
<exclude>log4j.xml</exclude>
<exclude>struts.properties</exclude>
</excludes>
<filtering>false</filtering>
</resource>
</resources>
以及网络资源:
<warSourceExcludes>**/context.xml</warSourceExcludes>
所以现在3个文件没有复制到WAR文件夹中。在下一步(webResources)中,它们将从活动配置文件的文件夹中复制。
我还添加了一个默认文件夹,其中包含具有常用值的3个文件。此默认文件夹中的文件也会被复制,但只能在配置文件的文件夹之后复制。由于资源未被覆盖,因此只有在资源尚不存在时才会复制它们。如果您在未激活配置文件的情况下构建,或者您可以定义合理的默认值,则此选项非常有用,如果文件相同,则每个配置文件都不需要复制该文件。
配置文件夹的结构:
-- config
|-- test
| |--log4j.xml
| | |--struts.properties
| | +--context.xml
| +-- prod
| | |--log4j.xml
| | +--context.xml
| +-- default
| |--log4j.xml
| |--struts.properties
| +--context.xml
...
我的pom.xml的webResources部分:
<webResources>
<!-- Resources from the activated profile folder -->
<resource>
<directory>/src/main/config/${environment}</directory>
<targetPath>META-INF/</targetPath>
<includes>
<include>context.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/config/${environment}</directory>
<targetPath>WEB-INF/classes/</targetPath>
<includes>
<include>
struts.properties
</include>
<include>
log4j.xml
</include>
</includes>
</resource>
<!-- Default resources in case some file was not defined in the profile folder -->
<!-- Files are not overwritten so default files will be copied only if it does not exist already -->
<resource>
<directory>/src/main/config/default</directory>
<targetPath>META-INF/</targetPath>
<includes>
<include>context.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/config/default</directory>
<targetPath>WEB-INF/classes/</targetPath>
<includes>
<include>
struts.properties
</include>
<include>
log4j.xml
</include>
</includes>
</resource>
</webResources>
答案 1 :(得分:1)
我认为您需要覆盖战争文件。在war类型的每个配置文件中创建一个依赖项而不是jar,它将覆盖当前war文件中的文件。
另一种可能性可能是maven-war-plugin的overlay configuration。
因此配置文件将激活您想要通过当前文件复制的文件。插件网站上还有quite some documentation以及一些示例
希望有效!
答案 2 :(得分:1)
看看这些问题/答案中的任何一个。一个可能适合你。
Run an ant task in maven build phase before war is packaged?
答案 3 :(得分:1)
另一次尝试:)
我玩过覆盖参数。我认为只替换webapp文件夹中的另一个war文件中的webapp文件夹中的文件。所以这对你的设置来说不是完美的。
然而,上面提到的webResource参数可以做到这一点:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.mimacom.maven.examples</groupId>
<artifactId>mimacom-war-overlays</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>${project.artifactId}</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.compiler.version>1.6</project.build.compiler.version>
<junit.version>4.9</junit.version>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>${project.build.compiler.version}</source>
<target>${project.build.compiler.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>prod</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<webResources>
<resource>
<directory>src/main/config/prod</directory>
</resource>
</webResources>
<!--<includes>-->
<!--<include>${basedir}/environments/overlay-1/css/styles.css</include>-->
<!--</includes>-->
<!--<overlays>-->
<!--<overlay>-->
<!--<includes>-->
<!--../environments/overlay-1/css/**-->
<!--</includes>-->
<!--</overlay>-->
<!--</overlays>-->
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>test</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<webResources>
<resource>
<directory>src/main/config/test</directory>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
激活的配置文件会将其他文件夹添加到war文件中。所以应该这样做!
答案 4 :(得分:1)
我看到你会使用相同的资源,但在每个配置文件中使用不同的配置(测试和产品)。
所以,我建议你使用这样的配置:
<profiles>
<profile>
<id>test</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>env</name>
<name>test</name>
</property>
</activation>
<build>
<filters>
<filter>test.properties</filter>
</filters>
</build>
</profile>
<profile>
<id>prod</id>
<activation>
<property>
<name>env</name>
<value>prod</value>
</property>
</activation>
<build>
<filters>
<filter>prod.properties</filter>
</filters>
</build>
</profile>
</profiles>
在这种情况下,我有两个配置文件,每个配置文件都使用“env”参数激活。 每个配置文件都有一个文件来过滤您的资源,将您的log4j.xml,struts.properties,context.xml文件放在src / main / resources中,并使用变量在每个配置文件中使用正确的配置。
希望有所帮助。
答案 5 :(得分:0)
以上是上述解决方案的简单版本,仅依赖于插入pom.xml的简单代码段。
使用以下命令构建默认(本地工作站)webapp:
mvn war:exploded
添加环境命令行参数,将文件从特定于环境的目录(如resources-prod)复制到目标WEB-INF / classes目录:
mvn war:exploded -Denvironment=prod
在pom.xml的项目元素中添加:
<!-- this profile will allow files in environment-specific folders like resources-prod or resources-test
to be added to the resulting war's classpath under WEB-INF/classes
to activate the profile, simply add '-Denvironment=prod' to your maven build command
this also works fine with war:inplace and war:exploded
-->
<profile>
<id>environment-specific</id>
<activation>
<property>
<name>environment</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<webResources>
<!-- note the order of the following resource elements are important.
if there are duplicate files, the first file copied will win
-->
<resource>
<!-- this is relative to the pom.xml directory -->
<directory>resources-${environment}</directory>
<!-- override default destination at root of war -->
<targetPath>WEB-INF/classes</targetPath>
</resource>
<resource>
<directory>src/main/resources</directory>
<targetPath>WEB-INF/classes</targetPath>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
</profile>
更多信息和link to working example。