Maven: как фильтровать один и тот же ресурс несколько раз с разными значениями свойств? - PullRequest
17 голосов
/ 22 июля 2010

Наш проект использует Log4J, настроенный через файл log4j.properties.У нас есть несколько производственных серверов, которые регистрируют в разных файлах журналов, так что журналы могут быть дифференцированы.Таким образом, log4j.properties для узла 1 выглядит следующим образом:

...
log4j.appender.Application.File=D:/logs/application_1.log
...
log4j.appender.tx_info.File=D:/logs/tx_info_1.log
...

, а log4j.properties для узла 2 выглядит как

...
log4j.appender.Application.File=D:/logs/application_2.log
...
log4j.appender.tx_info.File=D:/logs/tx_info_2.log
...

Мы уже используем профили Maven для создания конфигурации нашего сервера.До настоящего времени он содержал несколько отдельных файлов log4j.properties, которые отличались только именами файлов журнала, как показано выше.Я хотел бы сгенерировать эти файлы с помощью Maven, используя файл шаблона ресурса, например так:

...
log4j.appender.Application.File=${log.location}/application${log.file.postfix}.log
...
log4j.appender.tx_info.File=${log.location}/tx_info${log.file.postfix}.log
...

Легко запускать Maven несколько раз с разными значениями ${log.file.postfix}, чтобы каждый раз генерировать отдельный файл свойств журнала.,Однако я хотел бы, чтобы сгенерировал отдельный файл свойств (с разными именем и путем) для каждого сервера в одной сборке .Я уверен, что это можно сделать, например, с помощью плагина antrun, но я не знаком с этим.Какой самый простой способ добиться этого?

Ответы [ 4 ]

15 голосов
/ 23 июля 2010

(...) Я вполне уверен, что это можно сделать, например, с помощью плагина antrun, но я не знаком с этим.Какой самый простой способ добиться этого?

Вы действительно можете использовать resources:copy-resources и несколько <execution> в своем POM (обратите внимание, что resources:copy-resources не позволяет изменить имя целифайл хотя).

Предположим, у вас есть следующая структура:

$ tree .
.
├── pom.xml
└── src
    ├── main
    │   ├── filters
    │   │   ├── filter-node1.properties
    │   │   └── filter-node2.properties
    │   ├── java
    │   └── resources
    │       ├── log4j.properties
    │       └── another.xml
    └── test
        └── java

Где log4j.properties использует заполнители, а файлы filter-nodeN.properties содержат значения.Например:

# filter-node1.properties

log.location=D:/logs
log.file.postfix=_1

Затем в вашем pom.xml настройте плагин ресурсов и определите один <execution> для каждого узла для вызова copy-resources с определенным выходным каталогом и специальным фильтром для использования:

<project>
  ...
  <build>
    <resources>
      <!-- this is for "normal" resources processing -->
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering><!-- you might still want to filter them -->
        <excludes>
          <!-- we exclude the file from "normal" resource processing -->
          <exclude>**/log4j.properties</exclude>
        </excludes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.4.3</version>
        <executions>
          <execution>
            <id>copy-resources-node1</id>
            <phase>process-resources</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <outputDirectory>${basedir}/target/node1</outputDirectory>
              <resources>
                <resource>
                  <directory>src/main/resources</directory>
                  <filtering>true</filtering>
                  <includes>
                    <include>**/log4j.properties</include>
                  </includes>
                </resource>
              </resources>
              <filters>
                <filter>src/main/filters/filter-node1.properties</filter>
              </filters>
            </configuration>
          </execution>
          <execution>
            <id>copy-resources-node2</id>
            <phase>process-resources</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <outputDirectory>${basedir}/target/node2</outputDirectory>
              <resources>
                <resource>
                  <directory>src/main/resources</directory>
                  <filtering>true</filtering>
                  <includes>
                    <include>**/log4j.properties</include>
                  </includes>
                </resource>
              </resources>
              <filters>
                <filter>src/main/filters/filter-node2.properties</filter>
              </filters>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Запуск mvn process-resources приведет к следующему результату:

$ tree .
.
├── pom.xml
├── src
│   ├── main
│   │   ├── filters
│   │   │   ├── filter-node1.properties
│   │   │   └── filter-node2.properties
│   │   ├── java
│   │   └── resources
│   │       ├── log4j.properties
│   │       └── another.xml
│   └── test
│       └── java
└── target
    ├── classes
    │   └── another.xml
    ├── node1
    │   └── log4j.properties
    └── node2
        └── log4j.properties

С соответствующими значениями в каждом log4j.properties.

$ cat target/node1/log4j.properties 
log4j.appender.Application.File=D:/logs/application_1.log
log4j.appender.tx_info.File=D:/logs/tx_info_1.log

Этот вид работает, но многословно, и это может быть проблемой, если у вас приличное количество узлов.


Я пытался написать что-то более краткое и удобное в использовании с помощью плагина Maven AntRun, но не смогполучить задачу for из ant-contrib для работы под Maven (по неизвестной причине задача for не распознается), и я отказался от .

Вот альтернатива, использующаяMaven AntRun Плагин.Ничего сложного, без цикла, я просто копирую исходный файл в другое место, меняю его имя на лету и фильтрую содержимое:

  <plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.3</version>
    <executions>
      <execution>
        <id>copy-resources-all-nodes</id>
        <phase>process-resources</phase>
        <configuration>
          <tasks>
            <copy file="src/main/resources/log4j.properties" toFile="target/antrun/log4j-node1.properties">
              <filterset>
                <filter token="log.location" value="D:/logs"/>
                <filter token="log.file.postfix" value="_1"/>
              </filterset>
            </copy>
            <copy file="src/main/resources/log4j.properties" toFile="target/antrun/log4j-node2.properties">
              <filterset>
                <filter token="log.location" value="D:/logs"/>
                <filter token="log.file.postfix" value="_2"/>
              </filterset>
            </copy>
          </tasks>
        </configuration>
        <goals>
          <goal>run</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

Обратите внимание, что Ant по умолчанию использует @ в качестве разделителей длятокен (не удалось заставить его использовать разделители в стиле maven), поэтому log4j.properties стал:

log4j.appender.Application.File=@log.location@/application@log.file.postfix@.log
log4j.appender.tx_info.File=@log.location@/tx_info@log.file.postfix@.log

Но, поскольку эти значения кажутся специфичными для узла, вы рассматривали возможность использованиявместо системных свойств (что вы можете поместить в сценарии запуска)?Это то, что я уже сделал (с log4j.xml), оно работает хорошо, и это сильно упростит вещи.

3 голосов
/ 06 мая 2015

Хотя это немного устарело, я недавно натолкнулся на эту тему и хотел бы предложить обновленное решение с использованием iterator-maven-plugin.Обзор находится здесь: http://khmarbaise.github.io/iterator-maven-plugin/

Конкретным примером того, как вы можете достичь своей цели, было бы объединить плагин итератора с включенным ресурсом копирования и фильтром.Вы можете даже добавить файл пользовательских свойств для использования в качестве фильтра, если у вас есть другие атрибуты, уникальные для каждого узла с этим подходом.

<plugin>

    <groupId>com.soebes.maven.plugins</groupId>
    <artifactId>iterator-maven-plugin</artifactId>
    <version>0.3</version>

    <executions>
        <execution>
            <id>configure-log-properties</id>
            <phase>validate</phase>
            <goals>
                <goal>iterator</goal>
            </goals>
            <configuration>
                <iteratorName>log.file.postfix</iteratorName>
                <content>1,2,3,4,5</content>
                <pluginExecutors>

                    <pluginExecutor>
                        <plugin>
                            <artifactId>maven-resources-plugin</artifactId>
                            <version>2.7</version>
                        </plugin>

                        <goal>copy-resources</goal>

                        <configuration>
                            <outputDirectory>${project.build.directory}/nodes/${log.file.postfix}</outputDirectory>

                            <resources>
                                <resource>
                                    <directory>src/main/resources</directory>
                                    <includes>
                                        <include>log4j.properties</include>
                                    </includes>
                                    <filtering>true</filtering>
                                </resource>
                            </resources>
                        </configuration>

                    </pluginExecutor>
                </pluginExecutors>
            </configuration>
        </execution>
    </executions>
</plugin>
1 голос
/ 22 июля 2010

Вот несколько подходов, которые вы можете попробовать:

  1. используйте плагин antrun и задачу copy для создания дубликатов файла ресурсов в фазе generate-resources. Пример использования плагина antrun приведен в ответе на этот SO вопрос о копировании с maven . Вы могли бы даже использовать расширение свойства ant для расширения каждого $ {log.file.postfix} до определенного значения, либо литеральных значений, 1,2,3 и т. Д., Либо уникальных заполнителей, $ {log.file.postfix1}, $ { log.file.postfix2}, которые в конечном итоге заменяются, когда maven выполняет фильтрацию ресурсов.

  2. Вместо того, чтобы использовать antrun, используйте систему контроля версий, чтобы настроить несколько копий одного и того же файла. После этого вы можете запустить несколько экземпляров ресурсов : copy-resources target, для каждого из которых настроены разные значения свойств и указано другое имя целевого файла.

0 голосов
/ 06 января 2014

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

  <plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.3</version>
    <executions>
      <execution>
        <id>copy-resources-all-nodes</id>
        <phase>process-resources</phase>
        <configuration>
          <tasks>
             <macrodef name="copyConfigFile">
                <attribute name="node"/>

                <sequential>
                   <copy file="src/main/resources/log4j.properties"
                         toFile="target/antrun/log4j-@{node}.properties">
                      <filterset>
                         <!-- put the node-specific config in property files node1.properties etc -->
                         <filtersfile file="config/@{node}.properties"/>
                      </filterset>
                   </copy>
                </sequential>
             </macrodef>

             <copyConfigFile node="node1"/>
             <copyConfigFile node="node2"/>
             <copyConfigFile node="node3"/>
             ...

          </tasks>
        </configuration>
        <goals>
          <goal>run</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

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

Есть пример, как это сделать здесь

...