Как перезаписать файлы в файле WAR во время сборки maven?

у меня есть проект 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

как вы можете видеть, я включил ряд файлов конфигурации. Тот, кто находится в правильном месте в рамках проекта struture, т. е. внутри src/main/resources и src/main/webapp являются те, которые я обычно использую, когда я работаю в MyEclipse. Я могу использовать MyEclipse соединители для автоматического обновления развертывания, например, экземпляра Tomcat на моей машине dev. Я просто нажимаю "запустить сервер", и я могу отлаживать. На самом деле нет необходимости использовать Maven вообще в этом контексте.

затем, когда я хочу создать выпуск для другой среды, такой как тестирование или производство, я запускаю mvn -P test clean install и это строит хорошую войну.

моя цель-заменить файлы конфигурации внутри final 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 переменная) в правильное место внутри войны (или временная папка, которая будет сжата в войну) :

<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 С src/main/resources вместо одного из сказать src/main/configuration/prod/

извлечение из вывода Maven:

[INFO] Processing war project
[INFO] Copying webapp webResources [D:workspaceMyProject/src/main/config/prod] to [D:workspacesSITELWebfaunatargetWebfauna]
[INFO] Copying webapp webResources [D:workspaceMyProjectsrc/main/config/prod] to [D:workspacesSITELWebfaunatargetWebfauna]
[INFO] Copying webapp resources [D:workspaceMyProjectsrcmainwebapp]

как вы можете видеть на последней строчке, вещи из src/main/webapp копируется после, Таким образом перезаписывая мои пользовательские файлы : (

мой вопрос: Как заставить Maven использовать файлы "из активированного профиля" и как-то перезаписать "естественные" файлы ?

6 ответов


как указано во втором Q / A, заданный user944849, самым простым решением было отфильтровать исходные файлы, чтобы их можно было заменить файлами из папки профиля.

поэтому я добавил фильтрацию к стандартным ресурсам:

    <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
...

и раздел webResources моего pom.XML-код:

<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>


еще одна попытка :)

Я играл с параметром overlay. Я думаю, что только заменяет файлы в папке webapp у вас в другой файл в папке 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. Так что это должно сработать!


Я вижу, что вы будете использовать те же ресурсы, но с разной конфигурацией в каждом профиле (тест и prod).

Итак, я предлагаю вам использовать такую конфигурацию:

<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, распорки.свойства, контекст.xml-файлы в src / main / resources и использовать переменные для использования правильной конфигурации в каждом профиль.

надеюсь, что это поможет.


Я думаю, вам нужно наложить файлы войны. Либо создание зависимости в каждом профиле типа war вместо jar, которая будет накладывать файлы в текущем файле war.

другой возможностью может быть оверлея конфигурации Maven-war-плагина.

таким образом, профиль активирует файлы, которые вы хотите скопировать поверх текущих. Есть довольно документацию на сайте плагина, а также с некоторыми примеры

надеюсь, что это сработает!


вот более простая версия решений выше, которая полагается только на простой фрагмент, вставленный в pom.XML.

создайте веб-приложение по умолчанию (локальная рабочая станция) с помощью:

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>

и ссылка на рабочий пример.