12

我有一个在 Eclipse(更准确地说是 MyEclipse 10)中开发并使用 Maven 3 构建的 Java webapp 项目。

我有以下布局(仅包括与我的问题相关的文件:

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。

我的目标是将最终 WAR 中的配置文件替换为src/config/{environment}/.

我在我的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.xmlfromsrc/main/resources而不是 from the one 结尾说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 使用“来自激活的配置文件”的文件并以某种方式覆盖“自然”文件?

4

6 回答 6

13

正如user944849 给出的第二个 Q/A中所指出的,最简单的解决方案是过滤掉原始文件,以便它们可以被配置文件文件夹中的文件替换。

所以我在标准资源中添加了过滤:

    <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>
于 2012-10-05T06:44:57.310 回答
1

另一个尝试:)

我玩过覆盖参数。我认为这只替换 webapp 文件夹中的文件,你在 webapp 文件夹中的另一个 war 文件中。所以这对你的设置来说不是完美的。

然而上面提到的 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 文件中。所以这应该可以解决问题!

于 2012-10-05T12:32:28.810 回答
1

我认为您需要覆盖战争文件。在每个war类型的配置文件而不是jar中创建一个依赖项,这将覆盖当前war文件中的文件。

另一种可能性可能是 maven-war-plugin 的覆盖配置

因此配置文件将激活您要复制的文件而不是当前文件。插件站点上也有相当多的文档以及一些示例

希望有效!

于 2012-10-04T14:39:57.667 回答
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 中,并使用变量在每个配置文件中使用正确的配置。

希望有帮助。

于 2013-02-14T22:38:18.763 回答
1

看看这些问题/答案中的任何一个。一个可能对你有用。

在打包战争之前在 Maven 构建阶段运行 ant 任务?

构建战争时文件在maven项目中被覆盖

于 2012-10-04T15:57:39.837 回答
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>

更多信息和工作示例的链接

于 2014-02-14T21:03:55.137 回答