eclipse 如何在 maven 构建期间覆盖 WAR 文件中的文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12729513/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to overwrite files in the WAR file during maven build?
提问by Pierre Henry
I have a Java webapp project that I develop in Eclipse (more precisely MyEclipse 10) and build using Maven 3.
我有一个在 Eclipse(更准确地说是 MyEclipse 10)中开发并使用 Maven 3 构建的 Java webapp 项目。
I have the following layout (including only the files relevant to my problem :
我有以下布局(仅包括与我的问题相关的文件:
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
As you can see, I included a number of configuration files. The one who are at their proper location within the project struture, i.e. inside src/main/resources
and src/main/webapp
are the ones that I routinely use when I work in MyEclipse. I can use MyEclipse connectors to automatically update a deployment to e.g. a Tomcat instance on my dev machine. I just click "run server" and I can debug. No need to use Maven at all in this context actually.
如您所见,我包含了许多配置文件。位于项目结构中适当位置的那个,即内部src/main/resources
,src/main/webapp
是我在 MyEclipse 中工作时经常使用的那些。我可以使用 MyEclipse 连接器自动更新部署,例如我的开发机器上的 Tomcat 实例。我只需单击“运行服务器”即可调试。实际上在这种情况下根本不需要使用 Maven。
Then, when I want to build a release for another environment such as testing or production, I run mvn -P test clean install
and it builds a nice WAR.
然后,当我想为另一个环境(如测试或生产)构建一个版本时,我运行mvn -P test clean install
它并构建一个很好的 WAR。
My goal is to replace the configuration files inside the final WAR by those in src/config/{environment}/
.
我的目标是将最终 WAR 中的配置文件替换为src/config/{environment}/
.
I have set profiles in my pom.xml
:
我在我的配置文件中设置了pom.xml
:
<profiles>
<profile>
<id>test</id>
<properties>
<environment>test</environment>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<environment>prod</environment>
</properties>
</profile>
</profiles>
Then, I try to copy these resources from the specified profile (using the environment
variable) to the correct location inside the WAR (or the temporary folder that will be zipped into a WAR) :
然后,我尝试将这些资源从指定的配置文件(使用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>
Now this seems to work, except that the "standard" resources are copied to the directory AFTER this, so they overwrite these files. So I always end up with e.g. the log4j.xml
from src/main/resources
instead of the one from say src/main/configuration/prod/
现在这似乎有效,除了“标准”资源在此之后被复制到目录中,因此它们会覆盖这些文件。所以我总是以例如log4j.xml
fromsrc/main/resources
而不是 from 说src/main/configuration/prod/
Extract from the Maven output :
从 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]
As you can see on the last line, stuff from src/main/webapp
is copied AFTER, thus overwriting my custom files :(
正如您在最后一行中看到的那样,src/main/webapp
之后复制了其中的内容,从而覆盖了我的自定义文件:(
My question : How to force Maven to use the files "from the activated profile" and somehow OVERWRITE the "natural" files ?
我的问题:如何强制 Maven 使用“来自激活的配置文件”的文件并以某种方式覆盖“自然”文件?
回答by Pierre Henry
As pointed in the second Q/A given by user944849, the simplest solution was to filter out the original files so that they can be replaced by the files from the profile's folder.
正如user944849 给出的第二个Q/A所指出的,最简单的解决方案是过滤掉原始文件,以便它们可以被配置文件文件夹中的文件替换。
So I have added filtering to standard resources :
所以我在标准资源中添加了过滤:
<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>
And to the web resources :
和网络资源:
<warSourceExcludes>**/context.xml</warSourceExcludes>
So now the 3 files are not copied into the WAR folder. In the next step (webResources) they are copied from the active profile's folder.
所以现在这 3 个文件没有被复制到 WAR 文件夹中。在下一步 (webResources) 中,它们将从活动配置文件的文件夹中复制。
I also added a default folder containing the 3 files with common values. The files from this default folder are also copied, but only after the profile's folder ones. As the resources are not overwritten, they will be copied only if they don't already exist. This is useful if you build without a profile activated, or if you can define sensible default values, no each profile needs to replicate the file if it is identical.
我还添加了一个默认文件夹,其中包含具有通用值的 3 个文件。此默认文件夹中的文件也会被复制,但仅在配置文件的文件夹之后。由于资源不会被覆盖,因此仅当它们不存在时才会被复制。如果您在没有激活配置文件的情况下构建,或者如果您可以定义合理的默认值,则这非常有用,如果文件相同,则每个配置文件都不需要复制文件。
Structure of the config folder:
配置文件夹的结构:
-- config
|-- test
| |--log4j.xml
| | |--struts.properties
| | +--context.xml
| +-- prod
| | |--log4j.xml
| | +--context.xml
| +-- default
| |--log4j.xml
| |--struts.properties
| +--context.xml
...
And the webResources section of my pom.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>
回答by wemu
I think you need to overlay the war files. Either creating a dependency in every profile of type war instead of jar, that will overlay the files in your current war file.
我认为您需要覆盖War文件。在每个类型为 war 而不是 jar 的配置文件中创建依赖项,这将覆盖当前 war 文件中的文件。
Another possibility might be the overlay configurationof the maven-war-plugin.
另一种可能是maven-war-plugin的覆盖配置。
so the profile would activate the files you want to have copied over the current ones. There is quite some documentationon the plugin site as well with some examples
因此配置文件将激活您想要复制到当前文件的文件。插件站点上有很多文档以及一些示例
Hope that works!
希望有效!
回答by user944849
Take a look at either of these questions/answers. One may work for you.
看看这些问题/答案中的任何一个。一个可能适合你。
Run an ant task in maven build phase before war is packaged?
回答by wemu
another attempt :)
另一种尝试:)
I've played around with the overlay parameter. I think that only replaces files within webapp folder you have in another war file inside the webapp folder. So that is not the perfect thing for your setup.
我玩过覆盖参数。我认为这只会替换您在 webapp 文件夹内的另一个 war 文件中的 webapp 文件夹中的文件。所以这对你的设置来说不是完美的。
Yet the above mentioned webResource parameter can do this:
然而上面提到的 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>
The activated profiles will add additional folders to the war file. So that should do the trick!
激活的配置文件将向 war 文件添加额外的文件夹。所以这应该可以解决问题!
回答by chavocarlos
I see that you would use the same resources but with different configuration in each profile (test and prod).
我看到您将使用相同的资源,但在每个配置文件(测试和生产)中具有不同的配置。
So, I suggest you to use a configuration like this:
所以,我建议你使用这样的配置:
<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>
In this scenario, I have two profiles, each one is activated using "env" parameter. Each profile has a file to filter your resources, put your log4j.xml, struts.properties, context.xml files in src/main/resources and use variables to use right configuration in each profile.
在这种情况下,我有两个配置文件,每个配置文件都使用“env”参数激活。每个配置文件都有一个文件来过滤您的资源,将您的 log4j.xml、struts.properties、context.xml 文件放在 src/main/resources 中,并使用变量在每个配置文件中使用正确的配置。
Hope that helps.
希望有帮助。
回答by mkvalsvik
Here is a simpler version of the solutions above that relies only on a simple snippet inserted into pom.xml.
这是上述解决方案的更简单版本,它仅依赖于插入到 pom.xml 中的一个简单片段。
Build the default (local workstation) webapp with:
使用以下命令构建默认(本地工作站)webapp:
mvn war:exploded
Add an environment command line parameter to copy files from an environment-specific directory like resources-prod to the target WEB-INF/classes directory:
添加环境命令行参数以将文件从特定于环境的目录(如 resources-prod)复制到目标 WEB-INF/classes 目录:
mvn war:exploded -Denvironment=prod
Add this inside the project element of pom.xml:
在 pom.xml 的 project 元素中添加:
<!-- 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>
More info and link to working example.
更多信息和工作示例链接。