`

版本信息那些事

    博客分类:
  • Java
阅读更多

在做产品时,我们经常会遇到这样的需求:

  • 打Jar包时,需要压入产品的版本信息,甚至还有版权信息。
  • 在运行时,程序需要读取版本信息来做显示或者做分支处理。
向下兼容的一种实现方式是读取版本信息来做分支处理...Lucene是这种方式的代表之一。
版本信息的运行时获取的实现手段非常有限,大多使用 java.lang.Package来实现。

 

一、最简单的实现方式 - manifest

public class VersionInfo {

	public static String getVersion() {
		Package pkg = VersionInfo.class.getPackage();
		return (pkg != null ? pkg.getImplementationVersion() : null);
	}

}

这也是Spring的实现方法,但关键是版本信息的元数据来自哪里?这些信息存于Jar包内的MANIFEST.MF文件。该文件用于描述jar的情况,具体请见:http://baike.baidu.com/view/1857179.htm

 

这些属性中,和版本信息相关的属性是:

Implementation-Version: xxxx

 

 

 

二、ANT + manifest

思路是在build.xml里建立一个存放版本号的属性,并在打Jar包时,将版本号压入MANIFEST文件。程序在执行的时候,读取Jar包的MANIFEST来获取版本号。获取MENIFEST文件内版本号的方法没有任何改变,参考上一节。

 

build.xml

使用Eclipse自动生成build.xml后,在build.xml内增加这么几行:

	<property name="binary.version" value="1.0-SNAPSHOT" />

	<target name="package" description="package a jar" depends="cleanall, build-project">
		<jar jarfile="target/binary_version.jar" basedir="eclipse-build">
			<manifest>
				<attribute name="Implementation-Version" value="${binary.version}" />
				<attribute name="Main-Class" value="com.joshua.version.YourService" />
			</manifest>
		</jar>
	</target>

 

第一行是存放版本号的字段。名为package的target则负责把版本号压入manifest并制作jar包。

*注意:我存放class文件的目录是eclipse-build,大家需要把这个路径改成自己的目录(一般都是bin)

 

使用ant package命令打包,Jar包会生成在工程根目录下的target文件夹下。使用命令:java -jar binary_version.jar执行。就可以看到控制台上打印出来的版本信息了。

 

*注意:上述方式有个问题,就是不打包的情况下(比如在IDE里执行),是获取不到版本号的。

  

带SVN版本号的版本信息

当然现实的情况不可能这么简单,版本信息一般会带上Revision。比如,SVN的版本号。针对SVN,我们可以在build.xml里加个target:

  <target name="svnCheck" description="Use SVN to get the current revision" unless="disable-svnCheck">
    <exec executable="svn" logerror="true" outputproperty="svn.exec.result" failonerror="true" failifexecutionfails="true">
      <arg line="info"/>
    </exec>
    <loadresource property="svn.revision">
      <string value="${svn.exec.result}"/>
      <filterchain>
        <linecontains>
          <contains value="Last Changed Rev: "/>
        </linecontains>
        <tokenfilter>
            <!-- Remove all but the revision number -->
            <replaceregex pattern=".*: " replace=""/>
        </tokenfilter>
        <striplinebreaks/>
      </filterchain>
    </loadresource>
    <echo level="info" message="svn.revision=${svn.revision}"/>
  </target>

 

三、使用Annotation来实现

这种方式,我在Hadoop的源码中看到过,虽然繁琐,不过也挺有意思。优点是在非打包情况下也能工作。思路是定义1个Package级的annotation,annotation里定义了版本等属性。然后使用脚本自动获取版本信息并生成package-info.java,通过package-info传递Annotation的所有参数(包括版本信息),并且指定包名。在代码中使用反射获取被指定包的这个annotation,来获取版本信息。关于package-info的介绍,我这里就不做介绍了,google一下你就知道。

 

 

Annotation

 

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PACKAGE)
public @interface HadoopVersionAnnotation {
 
  /**
   * Get the Hadoop version
   * @return the version string "0.6.3-dev"
   */
  String version();
  
  ...
}

 

 生成package-info的脚本我就不给了,因为不同项目实现也不同。下面给出被生成的package-info.java:

@HadoopVersionAnnotation(version="1.0.3"...【省略其他属性】)
package org.apache.hadoop;

 

接着,在代码里可以使用如下方式获取版本信息:

    myPackage = HadoopVersionAnnotation.class.getPackage();
    version = myPackage.getAnnotation(HadoopVersionAnnotation.class);

 

 按上述方式,如果使用shell来生成package-info,那么我仍需要获取到软件的版本信息。版本可能源于SVN,或者GIT等等。下面提供些shell脚本供大家参考。

 

获取git的revision:

revision=`git log -1 --pretty=format:"%H"`

 

获取git的branch名

branch=`git branch | sed -n -e 's/^* //p'`

 

获取SVN的revision

revision=`svn info | sed -n -e 's/Last Changed Rev: \(.*\)/\1/p'`

 

 

 

分享到:
评论

相关推荐

    编程那些事之抽象编程_Ver6版本

    《编程那些事之抽象编程_Ver6版本》 在编程世界中,抽象编程是一种至关重要的思想,它是我们理解和解决问题的关键工具。"编程那些事之抽象编程_Ver6版本"是针对这一主题的深入探讨,旨在帮助程序员提升技能,更好地...

    java那些事儿chm

    8. **Java高级特性**:如Lambda表达式、Stream API、Optional类,这些是Java 8及更高版本引入的新特性。 9. **JVM原理**:Java虚拟机的工作原理,包括类加载机制、内存模型、JVM调优等。 10. **Spring框架**:如果...

    Linux那些事儿[完整版]自己整理

    【Linux那些事儿[完整版]】是一份关于Linux操作系统核心知识的综合整理,涵盖了从早期的2.6.10内核版本到2.6.22内核版本的更新与发展。这个资料集旨在深入浅出地讲解Linux系统的核心概念和技术,帮助读者理解Linux...

    linux那些事之我是USB

    本文将基于Linux 2.6.22内核版本,对Linux中的USB子系统进行深入剖析,旨在帮助读者理解USB设备如何与Linux系统交互,以及Linux内核是如何管理和调度这些设备的。 #### 二、USB架构概述 USB子系统由多个层次组成,...

    Linux那些事儿之我是Hub

    ### Linux那些事儿之我是Hub —— 2.6.22.1内核的usb hub driver分析 #### 引言 在《Linux那些事儿之我是Hub》这部作品中,作者通过一个颇具戏剧性的故事背景引入了对Linux 2.6.22.1内核中的USB Hub驱动程序的深入...

    linux那些事

    标题“linux那些事”和描述“适合初学者入门,当初就是看着这本书找到一份linux开发的工作”表明本文档是一本关于Linux操作系统的入门级读物。书籍内容涵盖了Linux的基础知识、内核结构、设备驱动编写等方面,特别...

    Linux那些事儿之我是U盘

    根据给定的信息,“Linux那些事儿之我是U盘”这一标题及描述主要聚焦于USB技术在Linux环境下的工作原理和技术细节。接下来,我们将基于这个主题展开深入探讨,涵盖USB技术的基本概念、USB在Linux系统中的实现机制...

    FPGA那些事儿 --TimeQuest静态 时序分析REV7.0 代码

    REV7.0可能指的是这个工具的一个具体版本,通常随着工具的升级,会带来新的特性和性能改进。 在使用TimeQuest进行时序分析时,设计者首先需要对设计进行综合,将高级语言如Verilog(标签提及的编程语言)编写的代码...

    course_s1_ZYNQ那些事儿-FPGA实验篇V1.04.pdf

    《course_s1_ZYNQ那些事儿-FPGA实验篇V1.04》这本教程详细介绍了ZYNQ开发平台的基础知识和使用方法。 首先,ZYNQ开发涉及的技能基础,对于初学者而言,需要具备一定的硬件知识和熟练的C语言编程能力。这是因为ZYNQ...

    Linux那些事儿之我是usb 第一和第二版都有,非常有用

    5. **USB设备描述符**:每个USB设备都有其独特的设备描述符,包含设备的基本信息,如设备类、子类、协议、版本、制造商、产品和序列号等。这些信息用于驱动程序的匹配和设备的识别。 6. **USB传输类型**:USB通信...

    IT项目管理那些事

    "IT项目管理那些事"这一主题,涉及了诸多方面,让我们深入探讨一下。 首先,我们要了解项目管理的基础知识。项目管理的五大过程组包括启动、规划、执行、监控和收尾。启动阶段确定项目目标和可行性,规划阶段制定...

Global site tag (gtag.js) - Google Analytics