在Maven中生成一个Version.java文件

我有一个使用Ant脚本构build的Java项目。 我正在尝试将该项目转换为Maven。

其中一个任务将生成一个名为Version.java的Java源文件,其中包含编译时间戳的静态String表示,如下所示:

package com.foo.bar; public final class Version { public static String VERSION="100301.1046"; } 

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=&quot;${buildtime}&quot;;${line.separator}" /> <echo file="src/${package.dir}/Version.java" append="true" message="}${line.separator}" /> <echo message="BUILD ${buildtime}" /> </target> 

是否有可能在Maven中使用生成源或其他简单的方法做类似的事情?

我不认为这是解决这类问题的好方法。

更好的方法是将版本信息放入一个将由Java程序读取的properties文件中:

您的属性文件将包含以下行:

 myapp.version=${project.version} 

然后,在您的pom.xml ,指出该文件将被Maven 过滤 :

 <resources> <resource> <directory>the/directory/that/contains/your/properties/file</directory> <filtering>true</filtering> </resource> </resources> 

当Maven构build你的应用程序时,它将会以它们的价值取代所有的${...} 。 默认情况下, ${project.version}定义了pom.xml的版本(即<version>标签的值)。

然后,在您的Java代码中,您只需加载properties文件并检索myApp.version属性值。

请注意,您可以使用Build Number插件来设置比当前版本更复杂的内容(例如,如果您想将构build时间放在属性中)。

如果你觉得ant有点丑,你也可以使用maven-replacer-plugin :可能是:

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

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@"; } 

这里是另一个解决scheme,将产生相同的拉尔夫自己的答案,使用POM属性过滤和模板文件:

模板文件(放置在src / main / resources / version中的VersionJava.template):

 package ${ver.package.name}; public final class ${ver.class.name} { public static String VERSION="${ver.buildtime}"; } 

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> 

现在这看起来可能过分了,但是它是非常通用的,我最喜欢的是我有一个可读格式的模板文件(而不是pom中的echo语句)。 这也允许我修改版本类,而不必更改pom

这是一个古老的问题,但是还有另外一个解决scheme可以很好的完成这个工作 (在Maven的意义上): 模板化Maven插件 。

正如您所期望的那样,使用此插件会将已处理的Java文件放入target/generated-sources文件夹中。 并将generated-sources文件夹添加到构buildpath。 您将不会再错误地检入处理的文件。

如何使用

首先把src/main/java-templates/com/foo/bar/Version.java放在下面:

 package com.foo.bar; public final class Version { public static final String VERSION = "${project.version}"; } 

然后将以下添加到您的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> 

文件夹target/generated-sources/java-templates被Maven添加到构buildpath中。

更多谷歌search后,我想出了这个(在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=&quot;${buildtime}&quot;;${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> 

它似乎运作良好,并产生这个Java文件:

 package com.foo.bar; public final class Version { public static String VERSION="100318.1211"; } 

基于@superole的答案 。 这是一个简化的版本,不需要设置额外的属性。 只是项目的版本被复制到Version.java。

Version.java放入src/main/templates

 package thepackage; public final class Version { public static String VERSION="${project.version}"; } 

指示mavenreplaceVersion.java中的标记

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

指示maven知道generated-sources/java为构buildpath:

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

最后,让Eclipse m2e

  • 了解新的构buildpath
  • 而不是陷入无限循环的构build。

第二点是通过在增量构buildeclipse期间禁用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需要被您的软件包replace:同时相应地调整targetPath 。 我发现在targetpath设置pathtargetpathsrc/main/templates中有许多子文件夹更容易。

正如@Romain所build议的那样,如果你可以等到包装或者自己过滤的文件,如果你不能,你可以从属性文件( /META-INF/maven/groupId/artifactId/pom.properties读取版本。如果它不提供你需要的一切)。

你想要坚持你的实际的Version类,然后看看这个线程在maven用户列表上,这正是提出了一个解决scheme(基于antrun插件,你将绑定在generated-sources阶段) 。

现在只需要很less的几行XML代码就可以使用模板化maven插件。

在Maven中查看我的答案在过滤源代码

一般来说,Maven的方式是描述你想要做什么。 然后数字如何 。 当需要数十或数百行的XML时,要么find正确的插件,要么编写它。 这就是创build模板-maven-plugin的基本原理:-)。

我正在使用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> 

此configuration生成以下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 

后来我正在用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); }