代码之家  ›  专栏  ›  技术社区  ›  Ralph java.is.for.desktop

在maven中生成version.java文件

  •  51
  • Ralph java.is.for.desktop  · 技术社区  · 15 年前

    我有一个用Ant脚本构建的Java项目。我正试图将项目转换为maven。

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

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

    蚂蚁的任务非常简单:

    <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中使用generate sources或其他一些简单的方法来做类似的事情?

    10 回复  |  直到 6 年前
        1
  •  77
  •   Romain Linsolas    11 年前

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

    更好的方法是将版本信息放在 properties 您的Java程序将读取的文件:

    属性文件将包含以下行:

    myapp.version=${project.version}
    

    然后,在你的 pom.xml ,表示文件将 filtered Maven:

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

    当maven构建您的应用程序时,它将替换所有 ${...} 根据它们的价值。默认情况下, ${project.version} 定义的版本 XML (即 <version> 标签)。

    然后,在Java代码中,您只需要加载 性质 归档并检索 myApp.version 属性值。

    注意,您可以使用 Build Number plugin 设置比当前版本更“复杂”的内容(例如,如果要将生成时间放入属性中)。

        2
  •  26
  •   MartyIX    6 年前

    你也可以使用 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@";
    
    }
    
        3
  •  14
  •   vegemite4me    8 年前

    这是一个老问题,但还有另一个解决办法 一份伟大的工作 这是完美的(在Maven意义上): Templating 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添加到生成路径。

        4
  •  12
  •   Superole    11 年前

    这是另一种解决方案,它将产生与拉尔夫自己的答案相同的结果, 使用POM属性筛选和模板文件:

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

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

    聚甲醛:

    <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语句)。 这还允许我修改version类,而不必更改pom

        5
  •  8
  •   Community CDub    8 年前

    基于 the answer by @superole . 这是一个简化版本,不需要设置额外的属性。只是将项目的版本复制到version.java中。

    Version.java 进入之内 src/main/templates :

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

    指示maven替换version.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>
    

    让马文知道 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>
    

    最后,让eclipse m2e

    • 注意新的构建路径
    • 而不是陷入无休止的循环建设。

    第二点是通过使用 maven-resources-plugin 在eclipse的增量构建期间。

    <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/模板 .

        6
  •  6
  •   Ralph java.is.for.desktop    15 年前

    经过更多的谷歌搜索,我想到了这个(在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";
    }
    
        7
  •  3
  •   Pascal Thivent    15 年前

    根据@romain的建议,您可以从属性文件中读取版本(或者 /META-INF/maven/groupId/artifactId/pom.properties 如果您可以等到打包或滚动您自己的过滤文件,如果您不能或如果它没有提供您需要的一切)。

    你想坚持你的实际 Version 同学们,看看 this thread 在maven用户列表中,它正为这个问题提出一个解决方案(基于将绑定到 generated-sources 相位)。

        9
  •  2
  •   Robert Niestroj    8 年前

    我用的是 Maven WAR Plugin 将信息添加到 MANIFEST.MF 文件并稍后在Java中读取此声明.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);
      }
    
        10
  •  1
  •   Community CDub    8 年前

    用很少几行XML代码来实现这一点的标准方法现在是使用模板化的Maven插件。

    看我的回答 Filtering source code in Maven

    一般来说,Maven的方法是 什么 你想这么做。 然后 图形 怎样 . 当how需要数十行或数百行xml时,要么找到合适的插件,要么编写它。这就是创建模板maven插件的基本原理:-)。