【问题标题】:How can I generate an API version from source?如何从源代码生成 API 版本?
【发布时间】:2015-07-30 22:10:22
【问题描述】:

我正在用 Java 编写一个 API 接口,我想添加一个方法,客户端将使用该方法来检查服务器使用的版本是否相同。

我可以添加 final String VERSION = "v1.2.3"; 之类的内容,但我想确保版本始终是最新的。

我想防止该文件可能不会更新。

我在运行时搜索类哈希计算(甚至在 maven 中的编译时可能会生成带有哈希的资源文件)。

当我使用 git 时,也许 Git 可以使用其提交哈希更新文件中的特殊标签,并在运行时为 API 中涉及的每个源返回一个 hashCode?​​p>

我该怎么做?

【问题讨论】:

  • RC,我已经在使用将 git 哈希写入资源文件的 git maven 插件。但我的问题是,涉及到 api 的类可能不是每个类都进入人工制品。我想在编译时创建一些类的哈希值,或者在运行时计算它,为算法提供类列表。
  • 我明白了,也许是stackoverflow.com/questions/9275780/…(关闭投票撤回)
  • 请注意,您可能应该将所有 API 类视为一个整体和版本,这将平滑客户端服务器版本检查

标签: java git maven


【解决方案1】:
  1. 创建一个类似这样的类:
package com.company;

import java.io.IOException;
import java.util.Properties;

public class VersionHelper
{
    static Properties versionProps=new Properties();

    static
    {
        try
        {
            versionProps.load(VersionHelper.class.getResourceAsStream("/version.properties"));
        }
        catch (IOException e)
        {
            System.err.println("Version von "+VersionHelper.class.getName()+" kann nicht ermittelt werden");
        }
    }

    public static String getArtifactId()
    {
        return versionProps.getProperty("artifact");
    }

    public static String getVersion()
    {
        return versionProps.getProperty("version");
    }

    public static String getBuild()
    {
        return versionProps.getProperty("build");
    }

    public static String getBuildTimeStamp()
    {
        return versionProps.getProperty("buildTimestamp");
    }
}
  1. .../src/main/resources 中创建文件version.properties。这是资源的 Maven 默认目录。

    artifact=${project.artifactId}
    version=${project.version}
    buildTimestamp=${build.timestamp}
    build=${buildNumber}
    
  2. 将这些属性添加到 pom.xml

<properties>
    <!-- look at http://rterp.wordpress.com/2012/03/16/stamping-version-number-and-build-time-in-properties-file-with-maven/ -->
    <build.timestamp>${maven.build.timestamp}</build.timestamp>
    <maven.build.timestamp.format>dd.MM.yyyy HH:mm</maven.build.timestamp.format>
</properties>
  1. 将此添加到 pom.xml 中的 &lt;build&gt; 部分:

    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
    
  2. 那么你可以在你的项目中使用来自VersionHelper的get方法

【讨论】:

  • 谢谢。我已经这样做了,但是不能使用构建时间戳,我们可以有多个开发人员在不同的计算机、不同的时间构建相同的 api,并且仍然使用相同的 api。 Artefact 版本可能会被忘记更新(在快照生命周期中甚至更多)。我最终将使用 git commit hash,它可能包含对 api 不重要的类,但它是最简单的方法。
【解决方案2】:

我可能无法完全理解您的问题。也许这会有所帮助..

由于 cmets 显示您正在使用 Maven,请查看 buildnumber-maven-plugin herehere 也给出了一些很好的用法示例。我已经能够毫不费力地使用它,而且它非常适合我。我想更进一步,创建一个页脚,在我的 Web 应用程序显示的每个页面上公开内部版本号,以便在我获得带有故障单的完整屏幕截图时准确了解正在使用的版本。

【讨论】:

  • 事实上,对 api 工件的修改可能不会显示 api 兼容性错误,具体取决于修改的内容。如果我通过 buildnumber 插件使用最后一个 git commit 哈希,即使是最小的修改也会引发 api 版本差异。我希望能够指定 api 所需的类列表。
  • 你是对的。这个想法不适合你,除非你可以从将你的工件打包成一个接口 jar 和一个实现 jar 中受益。然后,您可能会注意到仅接口 jar 上的哈希值的变化——这可能很有用,而且无论如何可能不是一个坏策略。
  • 是的,我确实应该分离代码,但我懒得这样做,但还不足以尝试找到我创建的 ant-run 解决方案:p
【解决方案3】:

好的,这就是我的解决方案,它肯定不是最有效的方法,但它确实有效:

在我的 pom.xml 中,我添加了这个:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.8</version>
    <executions>
        <execution>
            <phase>generate-resources</phase>
            <configuration>
                <target>
                    <macrodef name="gitlog">
                        <attribute name="lfile" />
                        <sequential>
                            <local name="gitHash"/>
                            <exec executable="git" outputproperty="gitHash">
                                <arg value="log" />
                                <arg value="--format=%H" />
                                <arg value="-n" />
                                <arg value="1" />
                                <arg value="--" />
                                <arg value="@{lfile}" />
                            </exec>
                            <concat append="true" destfile="target/classes/api_hashes.txt">@{lfile}:${gitHash}${line.separator}</concat>
                        </sequential>
                    </macrodef>

                    <loadfile property="api.classes" srcFile="api_classes.txt" />

                    <delete file="target/classes/api_hashes.txt"/>
                    <ac:for list="${api.classes}" param="classFile" delimiter="|" xmlns:ac="antlib:net.sf.antcontrib">
                        <sequential>
                            <gitlog lfile="@{classFile}" />
                        </sequential>
                    </ac:for>
                </target>
            </configuration>
            <goals>
                <goal>run</goal>
            </goals>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>ant-contrib</groupId>
            <artifactId>ant-contrib</artifactId>
            <version>1.0b3</version>
            <exclusions>
                <exclusion>
                    <groupId>ant</groupId>
                    <artifactId>ant</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
</plugin>

我的 api_classes.txt 文件包含一个由 char | 分隔的类文件(源)列表。 (无法使用回车符)在一行中,它会生成一个文件,其中包含源列表、char : 和搜索源的最后一个 git 哈希。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-19
    • 1970-01-01
    • 2012-04-25
    • 2017-01-21
    • 1970-01-01
    • 2020-04-26
    • 2017-05-16
    相关资源
    最近更新 更多