读过Hadoop源码的人一定不陌生,其实就是借鉴Hadoop源码里的启动工具类。
只不过Hadoop源码是用package-info.java来实现。
原理大致一样,通过打包脚本,在maven打包之前生成相关的信息载体文件放入项目资源文件中,然后进行maven打包。
项目启动时,加载资源文件到VersionInfo信息类中,给消息输出工具类进行使用。
由于工作中的项目是通过生成txt的版本文件而不是package-info.java文件,所以进行了修改。
具体的代码可以参考Hadoop源码里的org.apache.hadoop.hdfs.server.namenode.NameNode的main方法。
调用方式
public class TEST {
private static Logger LOG = LoggerFactory.getLogger(TEST.class.getName());
public static void main(String[] args) {
MessagesUtils.startupShutdownMessage(TEST.class, args, LOG);
// 处理后续业务逻辑
// ......
}
}
工具类
package com.hyr;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
/*******************************************************************************
* @date 2018-11-30 下午 4:23
* @author: <a href=mailto:>黄跃然</a>
* @Description: 消息工具类
******************************************************************************/
public class MessagesUtils {
/**
* 启动/关闭 消息打印
*
* @param clazz 启动clazz
* @param args
* @param LOG
*/
public static void startupShutdownMessage(Class<?> clazz, String[] args, final org.slf4j.Logger LOG) {
final String hostname = getHostname();
final String classname = clazz.getSimpleName();
LOG.info(
getMessageInfo(args, hostname, classname)
);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
LOG.info(toStartupShutdownString("SHUTDOWN MESSAGE: ", new String[]{
"Shutting down " + classname + " at " + hostname}));
}
});
}
/**
* 启动/关闭 消息打印
*
* @param clazz 启动clazz
* @param args
* @param LOG
*/
public static void startupShutdownMessage(Class<?> clazz, String[] args, final org.apache.log4j.Logger LOG) {
final String hostname = getHostname();
final String classname = clazz.getSimpleName();
LOG.info(
getMessageInfo(args, hostname, classname)
);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
LOG.info(toStartupShutdownString("SHUTDOWN MESSAGE: ", new String[]{
"Shutting down " + classname + " at " + hostname}));
}
});
}
/**
* Return a message for logging.
*
* @param prefix prefix keyword for the message
* @param msg content of the message
* @return a message for logging
*/
private static String toStartupShutdownString(String prefix, String[] msg) {
StringBuilder b = new StringBuilder("\n" + prefix);
b.append("\n/************************************************************");
for (String s : msg)
b.append("\n").append(prefix).append(s);
b.append("\n************************************************************/");
return b.toString();
}
/**
* 日志详情
*
* @param args
* @param hostname
* @param classname
* @return
*/
private static String getMessageInfo(String[] args, String hostname, String classname) {
return toStartupShutdownString("START_UP MESSAGE: ", new String[]{
" Starting " + classname,
" host = " + hostname,
" args = " + Arrays.asList(args),
" version = " + BrowserVersionInfo.getProjectVersion(),
" compiled time = " + BrowserVersionInfo.getCompiledTime(),
" revision = " + BrowserVersionInfo.getSVNVersion(),
" java = " + System.getProperty("java.version")}
);
}
/**
* Return hostname without throwing exception.
*
* @return hostname
*/
private static String getHostname() {
try {
return "" + InetAddress.getLocalHost();
} catch (UnknownHostException uhe) {
return "" + uhe;
}
}
}
VersionInfo类
package com.hyr;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/*******************************************************************************
* @date 2018-12-04 上午 9:53
* @author: <a href=mailto:>黄跃然</a>
* @Description:
******************************************************************************/
public class BrowserVersionInfo {
private static Logger LOG = LoggerFactory.getLogger(BrowserVersionInfo.class.getName());
private static String VERSION = "version:";
private static String DATATIME = "datetime:";
private static String SVNVERSION = "svn-version:";
private static String versionInfo;
private static String version_str = "";
private static String date_time_str = "";
private static String svn_version_str = "";
private static boolean isInit = false;
static {
try {
versionInfo = getVersionInfo();
if (versionInfo != null) {
versionInfo = versionInfo.replace(" ", "");
versionInfo = versionInfo.replaceAll("\n", "");
Pattern version = Pattern.compile(VERSION);
Pattern datetime = Pattern.compile(DATATIME);
Pattern svn_version = Pattern.compile(SVNVERSION);
Matcher version_matcher = version.matcher(versionInfo);
Matcher datetime_matcher = datetime.matcher(versionInfo);
Matcher svn_version_matcher = svn_version.matcher(versionInfo);
if (version_matcher.find() && datetime_matcher.find() && svn_version_matcher.find()) {
version_str = versionInfo.substring(version_matcher.end(), datetime_matcher.start());
date_time_str = versionInfo.substring(datetime_matcher.end(), svn_version_matcher.start());
svn_version_str = versionInfo.substring(svn_version_matcher.end());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* get browser version
*
* @return
*/
public static String getProjectVersion() {
return !version_str.isEmpty() ? version_str : "Unknown";
}
/**
* get compiled time
*
* @return
*/
public static String getCompiledTime() {
return !date_time_str.isEmpty() ? date_time_str : "Unknown";
}
/**
* Get the subversion revision number for the root directory
*
* @return the revision number, eg. "451451"
*/
public static String getSVNVersion() {
return !svn_version_str.isEmpty() ? svn_version_str : "Unknown";
}
public static void main(String[] args) throws IOException {
if (versionInfo != null) {
versionInfo = versionInfo.replace(" ", "");
System.out.println(versionInfo);
Pattern version = Pattern.compile(VERSION);
Pattern datetime = Pattern.compile(DATATIME);
Pattern svn_version = Pattern.compile(SVNVERSION);
Matcher version_matcher = version.matcher(versionInfo);
Matcher datetime_matcher = datetime.matcher(versionInfo);
Matcher svn_version_matcher = svn_version.matcher(versionInfo);
if (version_matcher.find()) {
System.out.println(version_matcher);
}
if (datetime_matcher.find()) {
System.out.println(datetime_matcher);
}
if (svn_version_matcher.find()) {
System.out.println(svn_version_matcher);
}
String version_str = versionInfo.substring(version_matcher.end(), datetime_matcher.start());
String date_time_str = versionInfo.substring(datetime_matcher.end(), svn_version_matcher.start());
String svn_version_str = versionInfo.substring(svn_version_matcher.end());
}
}
private static String getVersionInfo() throws IOException {
URL sourcePath = Main.class.getProtectionDomain().getCodeSource().getLocation();
ZipFile zipFile = new ZipFile(sourcePath.getPath());
Enumeration<? extends ZipEntry> entries = zipFile.entries();
for (; entries.hasMoreElements(); ) {
ZipEntry zipEntry = entries.nextElement();
String filename = zipEntry.getName();
if (filename.startsWith("ver_") && filename.endsWith(".txt")) {
InputStream resourceAsStream = BrowserVersionInfo.class.getClassLoader().getResourceAsStream(filename);
return IOUtils.toString(resourceAsStream);
}
}
return null;
}
/**
* 读取 InputStream 到 String字符串中
*/
public static String readStream(InputStream in) {
try {
//<1>创建字节数组输出流,用来输出读取到的内容
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//<2>创建缓存大小
byte[] buffer = new byte[1024]; // 1KB
//每次读取到内容的长度
int len = -1;
//<3>开始读取输入流中的内容
while ((len = in.read(buffer)) != -1) { //当等于-1说明没有数据可以读取了
baos.write(buffer, 0, len); //把读取到的内容写到输出流中
}
//<4> 把字节数组转换为字符串
String content = baos.toString();
//<5>关闭输入流和输出流
in.close();
baos.close();
//<6>返回字符串结果
return content;
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
}
MAVEN依赖
注:部分JDK不支持javafx,如果需要引用上面的javafx.runtime.VersionInfo功能。需要单独引入javafx的依赖包。
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<scope>provided</scope>
</dependency>
新增package-info实现,可以参考github项目。
Github地址: https://github.com/huangyueranbbc/StartUpShutDownMessageUtils