java Maven:如何使用不同的属性值多次过滤相同的资源?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3308368/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Maven: how to filter the same resource multiple times with different property values?
提问by Péter T?r?k
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,通过 log4j.properties 文件配置。我们有多个生产服务器,记录到不同的日志文件,以便日志可以区分。所以节点 1 的 log4j.properties 看起来像这样:
...
log4j.appender.Application.File=D:/logs/application_1.log
...
log4j.appender.tx_info.File=D:/logs/tx_info_1.log
...
while the log4j.properties for node 2 looks like
而节点 2 的 log4j.properties 看起来像
...
log4j.appender.Application.File=D:/logs/application_2.log
...
log4j.appender.tx_info.File=D:/logs/tx_info_2.log
...
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:
我们已经使用 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
...
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?
使用不同的${log.file.postfix}值多次运行 Maven以每次生成单个不同的日志属性文件很容易。但是,我想要的是在一个 build 中为每个服务器生成一个不同的属性文件(名称/路径不同)。我相当确定这可以完成,例如通过 antrun 插件,但我对此并不熟悉。实现这一目标的最简单方法是什么?
回答by Pascal Thivent
(...) 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?
(...) 我相当确定这可以完成,例如通过 antrun 插件,但我对此并不熟悉。实现这一目标的最简单方法是什么?
You could indeed use resources:copy-resourcesand several <execution>in your POM (note that resources:copy-resourcesdoesn't allow to change the name of the target file though).
你确实可以在你的 POM 中使用resources:copy-resources和几个<execution>(请注意,resources:copy-resources虽然不允许更改目标文件的名称)。
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.propertiesis using place holders and the filter-nodeN.propertiesfiles contain the values. For example:
在哪里log4j.properties使用占位符并且filter-nodeN.properties文件包含值。例如:
# filter-node1.properties
log.location=D:/logs
log.file.postfix=_1
Then, in your pom.xml, configure the resources plugin and define one <execution>per node to call copy-resourceswith a specific output directory and a specific filter to use:
然后,在您的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>
Running mvn process-resourceswould produce the following result:
运行 mvnprocess-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
With the appropriate values in each 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.
这有点工作,但很冗长,如果你有相当数量的节点,这可能是一个问题。
I tried to write something more concise and maintainable using the Maven AntRun Plugin but I couldn't get the .fortask from ant-contribto work under Maven (for an unknown reason, the fortask isn't recognized) and I gave up
我尝试使用 Maven AntRun 插件编写更简洁和可维护的东西,但我无法在 Maven 下获得.for任务ant-contrib(由于未知原因,for任务无法识别),我放弃了
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:
这是使用 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>
Note that Ant uses @by default as delimiters for token (couldn't get it to use maven style delimiters) so the log4j.propertiesbecame:
请注意,Ant@默认使用作为标记的分隔符(无法让它使用 maven 样式的分隔符),因此log4j.properties变为:
[email protected]@/[email protected]@.log
[email protected]@/[email protected]@.log
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.
但是,由于这些值似乎是特定于节点的,您是否考虑过使用系统属性(您可以放置在启动脚本中)?这是我已经完成的事情(使用log4j.xml),它运行良好,并且可以极大地简化事情。
回答by einsty
Although this is a bit old, I came across the thread recently and would like to propose an updated solution using the iterator-maven-plugin. An overview is found here: http://khmarbaise.github.io/iterator-maven-plugin/
虽然这有点旧,但我最近遇到了这个线程,并想提出一个使用 iterator-maven-plugin 的更新解决方案。概述可在此处找到:http: //khmarbaise.github.io/iterator-maven-plugin/
A specific example of how you can accomplish your goal would be to combine the iterator plugin with a copy resource and filter enabled. You could even add custom properties file to use as a filter in case you have other attributes that are unique per node with this approach.
如何实现目标的一个具体示例是将迭代器插件与启用的复制资源和过滤器相结合。您甚至可以添加自定义属性文件以用作过滤器,以防您使用此方法具有每个节点唯一的其他属性。
<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>
回答by mdma
Here are some approaches that you can try:
以下是一些您可以尝试的方法:
use the antrun plugin, and the
copytask to make duplicates of your resource file in thegenerate-resourcesphase. An example of using the antrun plugin is given in the answer to this SO question on copying with maven. You could even use ant's property expansion to expand each ${log.file.postfix} to a distinct value, either the literal values, 1,2,3 etc. or unique placeholders, ${log.file.postfix1}, ${log.file.postfix2} which are finally replaced when maven does the resource filtering.Rather than using antrun, use your version control system to set up multiple copies of the same file. You can then run multiple instances of the resources:copy-resourcesgoal, each with different property values configured, and a different target file name.
使用 antrun 插件,以及
copy在generate-resources阶段中制作资源文件副本的任务。使用 antrun 插件的示例在关于使用 maven 复制的这个 SO 问题的答案中给出。您甚至可以使用 ant 的属性扩展将每个 ${log.file.postfix} 扩展为不同的值,可以是文字值,1,2,3 等,也可以是唯一的占位符,${log.file.postfix1}, ${ log.file.postfix2} 最终在 maven 进行资源过滤时被替换。不要使用 antrun,而是使用您的版本控制系统来设置同一文件的多个副本。然后,您可以运行resources:copy-resources目标的多个实例,每个实例配置不同的属性值,以及不同的目标文件名。
回答by Justin Rowe
If there are a lot of target configurations that need to be copied, you could use the maven-antrun-plugin together with ant macrodef.
如果需要复制的目标配置很多,可以使用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>
If you really have a lot of target configurations, you could also use ant-contrib to iterate over a list of target configurations.
如果你真的有很多目标配置,你也可以使用 ant-contrib 来迭代目标配置列表。
There's an example how to do this here
有一个示例如何在此处执行此操作

