在Maven中生成Version.java文件

问题描述 投票:0回答:9

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

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

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>

是否可以使用generate-sources或其他一些简单方法在Maven中做类似的事情?

java maven-2 code-generation
9个回答
80
投票

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

更好的方法是将版本信息放入

properties
文件中,该文件将由 Java 程序读取:

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

myapp.version=${project.version}

然后,在您的

pom.xml
中,指示该文件将被 Maven filtered :

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

当 Maven 构建您的应用程序时,它将用它们的值替换所有

${...}
。默认情况下,
${project.version}
定义
pom.xml
的版本(即
<version>
标签的值)。

然后,在您的 Java 代码中,您只需要加载

properties
文件并检索
myApp.version
属性值。

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


30
投票

如果你觉得 ant 有点丑,也可以使用

maven-replacer-plugin
: 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>

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

}

24
投票

这是一个老问题,但是还有另一个解决方案可以完美地做到“出色的工作”(在 Maven 意义上):Template Maven Plugin 使用此插件会导致处理后的 Java 文件被放入

target/generated-sources

文件夹中,正如您所期望的那样。它将

generated-sources
下的文件夹添加到构建路径中。
您将不再错误签入已处理的文件。

使用方法

首先将以下内容放在

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添加到构建路径中。

    


13
投票

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



12
投票

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

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


10
投票
@superole

的回答。这是一个简化版本,无需设置额外的属性。只是将项目的版本复制到 Version.java 中。

Version.java

放入

src/main/templates
:
package thepackage;

public final class Version {

 public static String VERSION="${project.version}";

}

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

指示maven知道
generated-sources/java

作为构建路径(使用

build-helper-maven-plugin
): <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

注意新的构建路径
  • 并且不要陷入无限循环构建。
  • 第二点是通过在 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

需要更换为您的包装:同时相应地调整

targetPath
。我发现在
targetpath
中设置路径比在
src/main/templates
中设置许多子文件夹更容易。
    


4
投票
Maven WAR Plugin

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>

此配置生成以下 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); }



3
投票
/META-INF/maven/groupId/artifactId/pom.properties

;如果您不能或者无法提供您需要的所有内容,则可以滚动您自己的过滤文件) .


并且您是否想坚持使用实际的

Version

类,然后查看 Maven 用户列表上的

this thread
,它正是为此提出了一个解决方案(基于您将绑定到的 antrun 插件) generated-sources阶段)。
    


2
投票

请参阅我的答案

在 Maven 中过滤源代码

一般来说,Maven 的方式是描述你想要做的

什么

然后如何。当需要数十或数百行 XML 时,要么找到合适的插件来完成此任务,要么编写它。这就是创建 templateting-maven-plugin 的基本原理:-)。

© www.soinside.com 2019 - 2024. All rights reserved.