java - 使 Web 应用程序自动确定并了解其版本

标签 java web-applications build build-process

我的团队有两个团队:服务器团队和客户端团队。我们服务端团队会提供API供客户端团队调用。 API 有很多版本,因此我们需要匹配服务器版本和相应的客户端版本 - 例如,如果服务器版本号远大于其支持版本并需要更新,旧客户端将拒绝工作。

由于上述原因,我们需要将服务器的构建版本发送回客户端。目前,我们通过在 Config 类中添加静态字段来实现此目的。但我担心这样一个事实,即每次构建新服务器时我们都必须手动增加它 - 特别是当我们进行日常构建时。这个过程很容易出错,而且不太优雅。

在我的搜索中,我看到许多建议使用 Maven 插件来管理构建版本。尽管我高度赞赏自动过程,但它仍然不让服务器知道内部版本号。服务器应用程序应该能够通过 API 调用将其构建版本返回给客户端。

我想过将数字版本写入某处(远程数据库,服务器上的文件)。 有没有办法让构建过程自动增加构建版本,但应用程序本身也可以在运行时检索这个数字?

我们使用 Maven 构建并使用 Jenkin 作为集成构建服务器。

最佳答案

我通常从 Maven 打包在 JAR 中的 MANIFEST.MF 文件中读取版本。 默认情况下,它看起来像这样:

Manifest-Version: 1.0
Built-By: user
Build-Jdk: 1.6.0_35
Created-By: Apache Maven 3.0.4
Archiver-Version: Plexus Archiver

Name: Artifact
Implementation-Build: 1.14-SNAPSHOT
Version: 1.14-SNAPSHOT

从这个文件中,我读取了 Version 元素,并使用它来显示应用程序的构建版本(例如 WAR/EAR 中打包的 jar 的所有版本)。 像这样的代码应该可以工作:

public static String getApplicationVersion() {
        String version = null;
        try {
            final List<VersionsUtil.Version> moduleVersions = VersionsUtil.getModuleVersions(Thread.currentThread().getContextClassLoader());
            for (VersionsUtil.Version moduleVersion : moduleVersions) {
                if (moduleVersion.name.equals("<NAME OF ARTIFACT TO GET>")) {
                    version = moduleVersion.version;
                    break;
                }
            }
        } catch (IOException e) {
            // We'll return null...
        }
        return version;
    }


public class VersionsUtil {
    private static final Logger LOG = LoggerFactory.getLogger(VersionsUtil.class);

    /**
     * Returns a list of the module versions available for the given class loader.
     *
     * @param classLoader the class loader to return module versions for
     * @return a list of module versions
     * @throws IOException in case there's an error reading the manifest
     */
    public static List<Version> getModuleVersions(final ClassLoader classLoader) throws IOException {
        return processResources(classLoader.getResources("META-INF/MANIFEST.MF"));
    }

    private static List<Version> processResources(final Enumeration<URL> resources) throws IOException {
        final List<Version> moduleVersions = new ArrayList();
        while (resources.hasMoreElements()) {
            URL resource = resources.nextElement();
            Version v = process(resource);
            if (v != null) {
                moduleVersions.add(v);
            }
        }
        return moduleVersions;
    }

    private static Version process(final URL resource) {
        try {
            Properties p = readResource(resource);
            return createVersion(p);
        } catch (IOException e) {
            LOG.warn("Failed to read resource: " + resource, e);
            return null;
        }
    }

    private static Version createVersion(final Properties p) {
        Object name = p.get("Name");
        if (name != null) {
            return new Version((String) name, (String) p.get("Version"));
        }
        return null;
    }

    private static Properties readResource(final URL resource) throws IOException {
        LOG.trace("Reading resource: " + resource);
        InputStream is = resource.openStream();
        Properties p = new Properties();
        p.load(is);
        is.close();
        return p;
    }

    public static final class Version {
        String name;
        String version;

        private Version(final String name, final String version) {
            this.name = name;
            this.version = version;
        }

    }
}

更新: 如果您希望在 MANIFEST.MF 中包含 Jenkins 内部版本号,您可以使用以下内容配置您的 POM.XML:

  ...
  <plugin>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.2</version>
    <configuration>
      <archive>
        <manifestSections>
          <manifestSection>
            <name>${project.name} (${project.artifactId})</name>
            <manifestEntries>
              <Version>${project.version}${build.number}</Version>
            </manifestEntries>
          </manifestSection>
        </manifestSections>
      </archive>
    </configuration>
  </plugin>
  ...
  <properties>
     <build.number />
  </properties>
  ...

如果您有兴趣标记 WAR/EAR 文件,则必须相应地添加 list 配置。 然后,在 Jenkins 作业配置中,只需将 BUILD_NUMBER 参数传递给 Maven 进程,如下所示:-Dbuild.number=$BUILD_NUMBER

关于java - 使 Web 应用程序自动确定并了解其版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12792939/

相关文章:

Java Selenium - 从 Google map 实时交通 View 中选择一个元素

Java For 数组列表中的循环

java - 汉诺塔输出

java - build文件夹下的文件是生成的,不能编辑,不能重新build android工程

Android Gradle 问题 : Caused by: groovy. lang.MissingMethodException:没有方法签名

java - Hibernate (HQL) 查找参数列表中缺失的 id

python - 是否可以在不将 Pyramid 应用程序安装为鸡蛋的情况下运行它?

c# - 如何在 web 应用程序 asp.net c# 中显示错误消息框

java - 后续访问的Tomcat鉴权

c++ - 如何在 .pri 文件的内容前加上路径?