在 Maven 中生成 Version.java 文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2469922/
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
Generate a Version.java file in Maven
提问by Ralph
I have a Java project that I build using an Ant script. I am trying to convert the project to Maven.
我有一个使用 Ant 脚本构建的 Java 项目。我正在尝试将项目转换为 Maven。
One of the tasks generates a Java source file called Version.java that contains a static String representation of the compilation timestamp, as follows:
其中一项任务生成一个名为 Version.java 的 Java 源文件,其中包含编译时间戳的静态字符串表示,如下所示:
package com.foo.bar;
public final class Version {
public static String VERSION="100301.1046";
}
The Ant task is very simple:
Ant 任务非常简单:
<target name="version" depends="init" description="Create Version.java">
<echo file="src/${package.dir}/Version.java" message="package ${package.name};${line.separator}" />
<echo file="src/${package.dir}/Version.java" append="true" message="public final class Version {${line.separator}" />
<echo file="src/${package.dir}/Version.java"
append="true"
message=" public static String VERSION="${buildtime}";${line.separator}" />
<echo file="src/${package.dir}/Version.java" append="true" message="}${line.separator}" />
<echo message="BUILD ${buildtime}" />
</target>
Is it possible to do something similar in Maven, using generate-sources, or some other simple method?
是否可以在 Maven 中使用生成源或其他一些简单方法做类似的事情?
采纳答案by Ralph
After more Googling, I came up with this (in the pom.xml):
经过更多的谷歌搜索,我想出了这个(在 pom.xml 中):
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<goals>
<goal>run</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<tasks>
<property name="src.dir" value="${project.build.sourceDirectory}" />
<property name="package.dir" value="com/foo/bar" />
<property name="package.name" value="com.foo.bar" />
<property name="buildtime" value="${maven.build.timestamp}" />
<echo file="${src.dir}/${package.dir}/Version.java" message="package ${package.name};${line.separator}" />
<echo file="${src.dir}/${package.dir}/Version.java" append="true" message="public final class Version {${line.separator}" />
<echo file="${src.dir}/${package.dir}/Version.java" append="true"
message=" public static String VERSION="${buildtime}";${line.separator}" />
<echo file="${src.dir}/${package.dir}/Version.java" append="true" message="}${line.separator}" />
<echo message="BUILD ${buildtime}" />
</tasks>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
It seems to work well and produces this Java file:
它似乎运行良好并生成了这个 Java 文件:
package com.foo.bar;
public final class Version {
public static String VERSION="100318.1211";
}
回答by Romain Linsolas
I don't think this is the good way to solve this kind of issue.
我认为这不是解决此类问题的好方法。
A better way is to put the version information in a properties
file that will be read by your Java program:
更好的方法是将版本信息放在properties
Java 程序将读取的文件中:
Your properties file will contain the following line:
您的属性文件将包含以下行:
myapp.version=${project.version}
Then, in your pom.xml
, indicate that the file will be filteredby Maven :
然后,在您的 中pom.xml
,指示该文件将由Maven过滤:
<resources>
<resource>
<directory>the/directory/that/contains/your/properties/file</directory>
<filtering>true</filtering>
</resource>
</resources>
When Maven will build your application, it will replace all ${...}
by their value. By default, ${project.version}
defines the version of the pom.xml
(i.e. the value of the <version>
tag).
当 Maven 将构建您的应用程序时,它将${...}
用它们的值替换所有内容。默认情况下,${project.version}
定义版本pom.xml
(即<version>
标签的值)。
Then, in your Java code, you will just need to load the properties
file and retrieve the myApp.version
property value.
然后,在您的 Java 代码中,您只需加载properties
文件并检索myApp.version
属性值。
Note that you can use the Build Number pluginto set something more "complex" than just your current version (for example if you want to put the build time in your property).
请注意,您可以使用Build Number 插件来设置比当前版本更“复杂”的内容(例如,如果您想将构建时间放在您的属性中)。
回答by Pascal Thivent
As suggested by @Romain, you could read the version from a property file (either /META-INF/maven/groupId/artifactId/pom.properties
if you can wait until the packaging or roll your own filtered file if you can't or if it doesn't provide everything you need).
正如@Romain 所建议的,您可以从属性文件中读取版本(/META-INF/maven/groupId/artifactId/pom.properties
如果您可以等到打包或滚动您自己的过滤文件,如果您不能或它不提供您需要的一切)。
And is you want to stick with your actual Version
class, then have a look at this threadon the maven users list which is precisely proposing a solution for this (based on the antrun plugin that you'll bind on the generated-sources
phase).
并且您是否想坚持使用您的实际Version
课程,然后查看Maven 用户列表上的此线程,该线程正是为此提出了解决方案(基于您将在generated-sources
阶段上绑定的 antrun 插件)。
回答by Superole
Here is another solution that will produce the same as Ralph's own answer, using pom properties filtering and a template file:
这是另一个使用 pom 属性过滤和模板文件产生与 Ralph 自己的答案相同的解决方案:
The template file (VersionJava.template placed in src/main/resources/version):
模板文件(VersionJava.template放在src/main/resources/version):
package ${ver.package.name};
public final class ${ver.class.name} {
public static String VERSION="${ver.buildtime}";
}
The pom:
绒球:
<properties>
...
<ver.package.dir>com/foo/bar${project.artifactId}</ver.package.dir>
<ver.package.name>com.foo.bar${project.artifactId}</ver.package.name>
<ver.class.name>Version</ver.class.name>
<ver.buildtime>${maven.build.timestamp}</ver.buildtime>
<ver.template.dir>src/main/resources/version</ver.template.dir>
<ver.template.file>VersionJava.template</ver.template.file>
</properties>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>version/*</exclude>
</excludes>
</resource>
<resource>
<directory>${ver.template.dir}</directory>
<includes>
<include>*.java</include>
</includes>
<filtering>true</filtering>
<targetPath>${basedir}/src/main/java/${ver.package.dir}</targetPath>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<tasks>
<copy file="${ver.template.dir}/${ver.template.file}" tofile="${ver.template.dir}/${ver.class.name}.java" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<phase>compile</phase>
<configuration>
<tasks>
<delete file="${ver.template.dir}/${ver.class.name}.java" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Now this may seem excessive, but it is extremely versatile, and what I like most about it is that I have the template file in a readable format (rather than echo statements in the pom). This also allows me to modify the version class without having to change the pom
现在这可能看起来有些过分,但它非常通用,我最喜欢它的一点是我拥有可读格式的模板文件(而不是 pom 中的 echo 语句)。这也允许我修改版本类而不必更改 pom
回答by spupek
You can also use maven-replacer-plugin
if you feel ant is a little bit ugly:
The pom entry might be:
maven-replacer-plugin
如果你觉得 ant 有点难看,你也可以使用:pom 条目可能是:
<project>
...
<properties>
<version.template.file>src/main/java/com/stackoverflowVersion.java.template</version.template.file>
<version.file>src/main/java/com/stackoverflow/Version.java</version.file>
</properties>
...
<build>
<plugins>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>maven-replacer-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<file>${version.template.file}</file>
<outputFile>${version.file}</outputFile>
<replacements>
<replacement>
<token>@buildnumber@</token>
<value>${svn.revision}</value>
</replacement>
<replacement>
<token>@buildtime@</token>
<value>${maven.build.timestamp}</value>
</replacement>
<replacement>
<token>@pomversion@</token>
<value>${project.version}</value>
</replacement>
</replacements>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
The Version.java.template might be:
Version.java.template 可能是:
package com.stackoverflow;
public final class Version {
public static final String build_number="@buildnumber@";
public static final String build_time="@buildtime@";
public static final String pomversion="@pomversion@";
}
回答by Baptiste Mathus
The standard way to do just that with very few lines of XML code is now to use the templating-maven-plugin.
使用很少的 XML 代码行做到这一点的标准方法现在是使用 templating-maven-plugin。
See my answer in Filtering source code in Maven
In general, the Maven way is to describe whatyou want to do. Thenfigure how. When how requires tens or hundreds of lines of XML, either find the right plugin that does that, or write it. That was the rationale that created the templating-maven-plugin :-).
一般情况下,Maven的方式是描述什么你想做的事情。然后图如何。当 how 需要数十或数百行 XML 时,要么找到合适的插件,要么编写它。这就是创建模板 Maven 插件的基本原理:-)。
回答by koppor
Based on the answer by @superole. This is a simplified version without the need to set extra properties. Just the project's version is copied into Version.java.
基于@superole 的回答。这是一个不需要设置额外属性的简化版本。只是将项目的版本复制到 Version.java 中。
Put Version.java
into src/main/templates
:
把Version.java
为src/main/templates
:
package thepackage;
public final class Version {
public static String VERSION="${project.version}";
}
Instruct maven to replace the tokens in Version.java
指示maven替换Version.java中的token
<resources>
<resource>
<directory>src/main/templates</directory>
<includes>
<include>*.java</include>
</includes>
<filtering>true</filtering>
<targetPath>${project.build.directory}/generated-sources/java/thepackage</targetPath>
</resource>
</resources>
Instruct maven to know generated-sources/java
as build path:
指示 maven 知道generated-sources/java
构建路径:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/java/</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
Finally, let Eclipse m2e
最后让Eclipse m2e
- be aware of the new build path
- and not to fall into an endless loop build.
- 注意新的构建路径
- 并且不会陷入无限循环构建。
The second point is achieved by disabling using the maven-resources-pluginduring the incremental build of eclipse.
第二点是通过在 eclipse 的增量构建期间禁用使用maven-resources-plugin来实现的。
<pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<versionRange>[1.0,)</versionRange>
<goals>
<goal>parse-version</goal>
<goal>add-source</goal>
<goal>maven-version</goal>
<goal>add-resource</goal>
<goal>add-test-resource</goal>
<goal>add-test-source</goal>
</goals>
</pluginExecutionFilter>
<action>
<execute>
<runOnConfiguration>true</runOnConfiguration>
<runOnIncremental>true</runOnIncremental>
</execute>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<versionRange>[1.0.0,)</versionRange>
<goals>
<goal>resources</goal>
</goals>
</pluginExecutionFilter>
<action>
<execute>
<runOnConfiguration>true</runOnConfiguration>
<runOnIncremental>false</runOnIncremental>
</execute>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
thepackage
needs to be replaced by your package: Also adjust the targetPath
accordingly. I found it easier to set the path in targetpath
instead of having many subfolders in src/main/templates
.
thepackage
需要由您的包替换:也相应地调整targetPath
。我发现设置路径更容易,targetpath
而不是在src/main/templates
.
回答by Robert Niestroj
I'm doing it using the Maven WAR Pluginadding information to the MANIFEST.MFfile and later reading this MANIFEST.MF file in Java:
我正在使用Maven WAR 插件将信息添加到MANIFEST.MF文件,然后在 Java 中读取此 MANIFEST.MF 文件:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<Build-Time>${maven.build.timestamp}</Build-Time>
</manifestEntries>
</archive>
</configuration>
</plugin>
This configuration generates the following MANIFEST.MF file:
此配置生成以下 MANIFEST.MF 文件:
Manifest-Version: 1.0
Implementation-Title: MyApp
Implementation-Version: 2.11.0-SNAPSHOT
Built-By: niestroj
Specification-Title: MyApp
Implementation-Vendor-Id: com.mycompany
Build-Time: 2017-01-09 15:30
Created-By: Apache Maven 3.0.5
Build-Jdk: 1.8.0_40
Specification-Version: 2.11
And later i'm reading this in Java like this:
后来我在 Java 中这样阅读:
try {
Manifest manifest = new Manifest(getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF"));
Attributes attributes = manifest.getMainAttributes();
attributes.getValue("Implementation-Version");
attributes.getValue("Build-Time");
} catch (IOException ex) {
LOGGER.debug("Error reading manifest file information", ex);
}
回答by vegemite4me
This is an old question, but there is another solution that does a great jobthis perfectly (in the Maven sense): Templating Maven Plugin.
这是一个老问题,但还有另一个解决方案可以完美地完成这项工作(在 Maven 意义上):Templating Maven Plugin。
Using this plugin results in the processed Java file being put into the target/generated-sources
folder, as you would expect. And it adds the folder under generated-sources
to the build path. You will no longer check-in the processed file by mistake.
target/generated-sources
如您所料,使用此插件会将处理后的 Java 文件放入文件夹中。并将其下的文件夹添加generated-sources
到构建路径中。您将不再错误地签入已处理的文件。
How to use
如何使用
First put the following under src/main/java-templates/com/foo/bar/Version.java
:
首先将以下内容放在src/main/java-templates/com/foo/bar/Version.java
:
package com.foo.bar;
public final class Version {
public static final String VERSION = "${project.version}";
}
Then add the following to your POM:
然后将以下内容添加到您的 POM 中:
<build>
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>templating-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>filtering-java-templates</id>
<goals>
<goal>filter-sources</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
The folder target/generated-sources/java-templates
is added to the build path by Maven.
该文件夹target/generated-sources/java-templates
由 Maven 添加到构建路径中。