Подтвердить что ты не робот

Maven: как фильтровать один и тот же ресурс несколько раз с разными значениями свойств?

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

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

в то время как log4j.properties для node 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}, чтобы генерировать каждый отдельный файл свойств журнала каждый раз. Однако я бы хотел, чтобы генерировал отдельный файл свойств (с именем /path different) для каждого сервера в одной сборке. Я достаточно уверен, что это можно сделать, например. через плагин antrun, но я не знаком с этим. Каков самый простой способ достичь этого?

4b9b3361

Ответ 1

(...) Я уверен, что это можно сделать, например. через плагин 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> за node, чтобы вызвать 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 Plugin, но я не мог получить задачу for из ant-contrib для работы в Maven (по неизвестной причине, задача for не распознается), и я отказался от.

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

  <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 стал:

[email protected]@/[email protected]@.log
[email protected]@/[email protected]@.log

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

Ответ 2

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

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

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

Ответ 3

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

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

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

Ответ 4

Если существует много целевых конфигураций, которые нужно скопировать, вы можете использовать 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/[email protected]{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 для перебора списка целевых конфигураций.

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