【问题标题】:What is a good way to handle a version number in a Java application?在 Java 应用程序中处理版本号的好方法是什么?
【发布时间】:2009-04-20 22:30:29
【问题描述】:

我正在使用 Java 和 Swing 应用程序框架开发桌面应用程序。我有一个关于盒子的应用程序,我想让那个盒子包含一些正在测试的版本的指示。我的偏好是以自动方式更改该值。我正在使用 CruiseControl 构建应用程序,触发对 SVN 的提交。

其他人使用什么机制来完成这项工作?是否有一个 about box 版本号库或一组 ant 相关工具,我可以在我的构建过程中放置​​它们?

我不是在寻找部署选项或自动检查更新或类似的东西。我只是希望能够在 about 框中询问测试人员是什么版本并获得可靠的答案。

【问题讨论】:

    标签: java version


    【解决方案1】:

    你把它弄得太复杂了。 SVN 以宏的形式提供版本号,类似于 CVS。

    创建一个包含常量的简单接口,并让 SVN 通过宏实例化它,例如

    public interface IVersionNumber {
        public static final String version = "$Id$" ;
    }
    

    您需要告诉 SVN 在该文件上使用关键字,如

    $ svn propset svn:keywords “Id”IVersion.java

    您可以阅读属性here

    【讨论】:

    • 它不能仅仅来自一个文件。 SVN 提供了一个宏来获取该文件的最新修订号。我的目标是不必每次提交时都触摸该文件。
    • 不,设置关键字替换正是您想要的。您不必触摸文件; SVN 处理。请记住,由于 SVN 使用原子修订,因此 所有 文件的版本号是相同的。
    • Svn 关键字只有在它们出现的文件更新时才会更新。对其他文件的不相关更改不会更新 Id svn 关键字。 Svn 使用原子修订的事实并不意味着存储库中的所有文件都具有相同的修订号。
    • @Charlie:你确定吗?我刚刚用 svn 1.5.1 创建了一个新的存储库。 rev 1:添加了文件 a 和 b(使用包含 $Id$ 关键字并设置了 svn:keywords),rev 2:更改了文件 b。然后我开始创建一个新的结帐:文件 a 中的 ID 关键字被扩展以指示修订版 1 是最后一次更改。新结帐的行为与 svn:keywords 的更新完全一样
    • 查理,对不起,你错了! svnbook.red-bean.com/en/1.5/… 。它在整个页面上,但引用:“由于存储库有一个单一的、全局递增的修订号,许多人认为 $Rev$ 关键字的值反映了这个数字。但是 $Rev$ 扩展以显示文件更改的最后一个修订版,而不是它更新到的最后一个修订版。”其他关键字同理。
    【解决方案2】:

    我将通过说明我使用Apache Maven 来构建这篇文章开始。您也可以使用 Ant 或其他工具做类似的事情,但这是我使用 maven 所做的。

    我发现处理此问题的最佳方法是使用项目的版本加上 subversion 修订作为内部版本号。从 Maven 中,您可以包括以下内容。这将为您提供作为 ${scm.revision} 的 subversion 修订号。

    <build>
        <plugins>
          <plugin>
            <artifactId>maven-scm-plugin</artifactId>
            <executions>
              <execution>
                <id>getting-scm.revision</id>
                <phase>validate</phase>
                <goals>
                  <goal>update</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    

    之后,我将其用作 jar 文件清单的一部分作为实现版本。

      <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.1</version>
        <configuration>
          <archive>
            <manifestEntries>
              <Implementation-Version>${this.version}.${scm.revision}</Implementation-Version>
            </manifestEntries>
          </archive>
        </configuration>
      </plugin>
    

    这样做的好处是您可以使用以下代码从代码中访问它:

    Package p = getClass().getPackage();
    String version = p.getImplementationVersion();
    

    这会为您提供完整的内部版本号,例如“1.0.13525”,其中最后一个数字是颠覆修订版。有关设置的更多信息,您可以查看完整的 blog post 我在这个问题上做了一段时间。

    【讨论】:

    • 太棒了!也可以使用 Ant 完成吗? (对不起,Java 世界中的 n00b)
    • p.getImplementationVersion();每次我尝试调用它时都会返回 null
    • 确保您没有从 IDE 运行。必须有一个 jar 才能找到清单条目。
    • 如果您不介意默认设置,可以使用一种简写方式来添加实现条目。见maven.apache.org/shared/maven-archiver/examples/manifest.html
    【解决方案3】:

    让构建脚本创建一个包含版本的属性文件。直接从 SVN 获取修订号是个好主意。这样你就可以在测试中引用它。将此属性文件放入打包的 jar 中并在运行时读取它。我们通常将主要和次要版本设置为 ant scrpt 的参数,而修订版由 SVN 自动管理并为参考提供一致的内部版本号。

    这个 sn-p 目标运行 svn 命令行并输出到一个临时文件 (svndump)。 然后构造 xx.yy.zz 字符串,将其放在另一个文件中,该文件稍后将包含在 jar 中。 注意xx.yy取自外部参数,这是major-minor版本。

    <target name="getrev">
        <exec executable="svn" output="svndump">
            <arg value="info"/>
            <arg value="${my.svn.url}"/>
        </exec>
    
        <property file="svndump"/>
        <property name="my.build" value="${Revision}"/>
        <property name="my.rev" value="${my.ver}.${my.build}"/>
        <echo message="current revision is ${my.rev}"/>
    
        <property name="my.dir.dist" value="${my.dir.root}/dist/${my.rev}"/>
        <echo message="${my.rev}" file="${my.dir.projects}/revision"/>
    
        <delete file="svndump"/>
    </target>
    

    【讨论】:

    • 有一个名为 SVN-Ant 的项目可以为你做 exec 的事情。
    • 是的,svn-ant 也可以。虽然我记得我尝试过的时候,但存在一些依赖问题。或许现在更成熟了,值得一试。
    • 这也可以在没有中间文件的情况下完成:&lt;target name="scm-version"&gt; &lt;exec executable="svn" outputproperty="svnOutput" &gt; &lt;arg value="info"/&gt; &lt;arg value="."/&gt; &lt;/exec&gt; &lt;loadproperties prefix="svn"&gt; &lt;propertyresource name="svnOutput"/&gt; &lt;/loadproperties&gt; &lt;property name="scm.version" value="${svn.Revision}"/&gt; &lt;echo message="current revision is ${scm.version}"/&gt; &lt;/target&gt;
    【解决方案4】:

    在 Maven 中,我使用了 buildnumber-maven-plugin,它从 Subversion 获取修订号,或者使用序列或时间戳,然后用于替换您喜欢的 ${buildNumber} 占位符。我想其他构建工具和持续集成服务器也有类似的功能。使用“ build number”搜索您最喜欢的搜索引擎。

    【讨论】:

      【解决方案5】:

      我们已经使用JReleaseInfo 很长时间了。您可以在 Ant 脚本中设置它(我们的项目不使用 Maven),它会自动调整版本号。它还有一些很好的补充,因为它生成了一个包含所有信息的类。您可以在代码中调用该类以准备好使用的字符串,或从命令行调用该类以使其打印出版本号,而无需更改任何代码。

      【讨论】:

        【解决方案6】:

        由于我使用cruise controlAnt 来构建所有内容,因此至少现在我最终使用传递给ant 调用的${label} 属性来构建项目。在我的 ant 文件中,我使用 Ant "replace" task 更改包含名为 Application.version 的 about 框资源的属性文件以包含该标签。

        我打算从label incrementer 更改为svn label incrementer,然后以这种方式使用svn 修订号。它只是多一点工作,它需要我对巡航控制配置文件进行更改。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-01-14
          • 2012-08-26
          • 2021-10-28
          • 1970-01-01
          • 2010-11-27
          • 2013-01-28
          • 2015-02-03
          相关资源
          最近更新 更多