本文介绍了Maven:如何使用不同的属性值多次过滤相同的资源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的项目使用Log4J,通过log4j.properties文件配置。我们有多个生产服务器,可以记录到不同的日志文件,以便区分日志。所以节点1的log4j.properties如下所示:

Our project uses Log4J, configured via log4j.properties file. We have multiple production servers, which log to different log files, so that the logs can be differentiated. So log4j.properties for node 1 looks like this:

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

,而节点2的log4j.properties看起来像

while the log4j.properties for node 2 looks like

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

我们已经使用Maven配置文件生成我们的服务器组态。到目前为止,它包含几个不同的log4j.properties文件,这些文件仅在日志文件名中有所不同,如上所示。我想使用像这样的资源模板文件使用Maven生成这些文件:

We already use Maven profiles for generating our server configuration. Up to now it contained several distinct log4j.properties files which differed only in the log file names as shown above. I would like to generate these files with Maven using a resource template file like this:

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

这很容易使用不同的 $ {log.file.postfix} 值多次运行Maven,每次都生成一个不同的日志属性文件。但是,我想要的是为一个版本中的每个服务器生成一个不同的属性文件(名称/路径不同)。我很确定这可以做到,例如通过antrun插件,但我不熟悉。实现这一目标的最简单方法是什么?

It is easy to run Maven multiple times with different ${log.file.postfix} values to generate a single different log property file each time. However, what I would like is to generate a distinct property file (with the name/path different) for each server in one build. I am fairly sure this can be done, e.g. via the antrun plugin, but I am not familiar with that. What is the simplest way to achieve this?

推荐答案

您确实可以使用资源:copy-resources 和几个< execution> (请注意资源:copy-resources 不会允许更改目标文件的名称)。

You could indeed use resources:copy-resources and several <execution> in your POM (note that resources:copy-resources doesn't allow to change the name of the target file though).

我们假设你有以下结构:

Let's assume you have the following structure:

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

Where log4j.properties 正在使用占位符, filter-nodeN.properties 文件包含值。例如:

Where log4j.properties is using place holders and the filter-nodeN.properties files contain the values. For example:

# filter-node1.properties

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

然后,在你的 pom中.xml ,配置资源插件并为每个节点定义一个< execution> 以调用 copy-resources 具有特定的输出目录和要使用的特定过滤器:

Then, in your pom.xml, configure the resources plugin and define one <execution> per node to call copy-resources with a specific output directory and a specific filter to use:

<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 会产生结果如下:

Running mvn process-resources would produce the following result:

$ 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

这种方法很有用,但是很冗长,如果你有相当数量的节点,这可能会有问题。

This kinda works, but is verbose and this might be a problem if you have a decent amount of nodes.

.

这是使用Maven AntRun插件的替代方案。没有什么复杂的,没有循环,我只是将源文件复制到另一个位置,动态更改其名称并过滤内容:

Here is an alternative using the Maven AntRun Plugin. Nothing complicated, no loop, I'm just copying the source file to another location, changing its name on the fly and filtering the content:

  <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 变为:

Note that Ant uses @ by default as delimiters for token (couldn't get it to use maven style delimiters) so the log4j.properties became:

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






但是,由于这些值似乎是特定于节点的,您是否考虑使用系统属性(您可以将其置于启动脚本中)?这是我已经完成的事情(使用 log4j.xml ),它运行良好,可以大大简化事情。


But, since these values seem to be node specific, did you consider using system properties instead (that you could place in the startup scripts)? This is something I've already done (with a log4j.xml), it works well and it would highly simplify things.

这篇关于Maven:如何使用不同的属性值多次过滤相同的资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 20:55