Zhiqim Kernel即知启蒙内核,是Zhiqim Framework的核心,负责工程的生命周期管理:包括工程开发和发布的目录结构管理、统一的配置规约、单多例服务接口定义、服务启动运行更新和销毁管理。并提供基础开发工具:包括工具类、日志类、线程池、JSON/XML编解析、HTTP客户端、时钟任务定时器等。
Zhiqim.java14KB
/*
* 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙,邂逅框架梦]
*
* https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
*
* Zhiqim Kernel is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.zhiqim.kernel;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.jar.JarEntry;
import org.zhiqim.kernel.annotation.AnGlobal;
import org.zhiqim.kernel.annotation.AnNew;
import org.zhiqim.kernel.config.Config;
import org.zhiqim.kernel.config.Group;
import org.zhiqim.kernel.config.Item;
import org.zhiqim.kernel.constants.ZhiqimConstants;
import org.zhiqim.kernel.logging.Log;
import org.zhiqim.kernel.logging.LogFactory;
import org.zhiqim.kernel.model.FilterHandler;
import org.zhiqim.kernel.model.Filters;
import org.zhiqim.kernel.model.results.RE;
import org.zhiqim.kernel.service.Service;
import org.zhiqim.kernel.util.Annotations;
import org.zhiqim.kernel.util.Classes;
import org.zhiqim.kernel.util.Closes;
import org.zhiqim.kernel.util.Files;
import org.zhiqim.kernel.util.Jars;
import org.zhiqim.kernel.util.Resources;
import org.zhiqim.kernel.util.Systems;
import org.zhiqim.kernel.util.Validates;
/**
* 知启蒙工程入口类<br><br>
*
* 一、判断是否是命令,如果是转到ZhiCommand处理
* 二、启动工程,调用startup方法
* 1.检查Java版本
* 2.加载配置文件信息<br>
* 3.注册监听<br>
* 4.加载ClassPath和ClassLoader<br>
* 5.加载工程服务<br>
* 6.生成工程注册Shutdown锚
*
* @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
*/
public final class Zhiqim implements ZhiqimConstants
{
private static final Log log = LogFactory.getLog(Zhiqim.class);
private static ZhiqimClassLoader zClassLoader;
/** 不允许实例化 */
private Zhiqim(){}
/** 工程启动入口 */
public static void main(String[] args)
{
if (args.length == 0)
{//无参数,开发环境启动
startup(true);
}
else if (args.length == 1 || args.length == 2)
{//有1-2参数
if (Z_START_A.equals(args[0]))
{//生产环境启动
startup(false);
}
else
{//其他6种命令
ZhiqimCommand.command(args);
}
}
else
{//不支持的参数
System.out.println("不支持的参数,请使用-h查看支持的参数");
}
}
/** 工程启动 */
private static void startup(boolean development)
{
//1.检查版本
if (!chkJavaVersion())
{
System.exit(1);
return;
}
//2.加载配置文件
if (!loadConfig())
{
System.exit(1);
return;
}
//3.注册监听端口
if (!registerMonitor())
{
System.exit(1);
return;
}
//注册监听端口成功之后表示开始初始化
log.info("系统[%s]-版本[%s]初始化开始...\r\n", Z.conf().getName(), Z.conf().getVersion());
//4.创建类加载器
if (!createClassLoader(development))
{
System.exit(1);
return;
}
//5.创建服务
if (!createServices())
{
System.exit(1);
return;
}
//6.注册工程关闭锚
Runtime.getRuntime().addShutdownHook(new ZhiqimHook());
//初始化完成打印日志
log.info("系统[%s]-版本[%s]初始化完成!!!\r\n", Z.conf().getName(), Z.conf().getVersion());
}
/** 检查JAVA版本 */
public static boolean chkJavaVersion()
{
String vers = Systems.getJavaVersion();
if (vers.compareTo("1.7") < 0)
{
System.out.println("JDK版本不能低于[1.7]");
System.out.println("java.vm.info: " + Systems.getVmInfo());
System.out.println("java.vm.name: " + Systems.getVmName());
System.out.println("java.vm.version: " + Systems.getVmVersion());
return false;
}
return true;
}
/** 初始化配置文件 */
private static boolean loadConfig()
{
//先检查xml再检查ini
String path = null;
if (Files.exists(Z_CONF_ZHIQIM_XML))
path = Z_CONF_ZHIQIM_XML;
else if (Files.exists(Z_CONF_ZHIQIM_INI))
path = Z_CONF_ZHIQIM_INI;
if (path == null)
{
log.error("配置文件[%s]和[%s]都不存在,请按手册配置目录结构", Z_CONF_ZHIQIM_XML, Z_CONF_ZHIQIM_INI);
return false;
}
Config config = new Config(Z_NAME, path);
try
{
//1.加载根配置文件
config.load();
//1.1检查[boot]下name,version,port三个字段是否必须
if (!config.hasGroup(Z_BOOT) || !config.hasItem(Z_BOOT, Z_ITEM_NAME) || !config.hasItem(Z_BOOT, Z_ITEM_VERSION) || !config.hasItem(Z_BOOT, Z_ITEM_PORT))
{
log.error("配置文件[boot]组中name,version,port必须的,请配置好再启动");
return false;
}
//1.2把配置加到全局表中
String result = Z.conf().add(config);
if (result != null)
{
log.error("根配置文件[%s]在这里[%s]有配置错误", path, result);
return false;
}
}
catch(Exception e)
{
log.error("初始化配置文件[%s]时异常", e, path);
return false;
}
//2.判断是否需要加载其他的配置文件
if (config.hasGroup(Z_CONFIG))
{
Collection<Item> itemList = config.getItemList(Z_CONFIG);
for (Item item : itemList)
{//2.1循环加载
try
{
Config conf = new Config(item.getKey(), item.getString()).load();
//2.2加到全局表中,失败退出
String result = Z.conf().add(conf);
if (result != null)
{
log.error("配置文件[%s]存在和别的配置文件相同的配置组[%s]", item.getString(), result);
return false;
}
}
catch(Exception e)
{
log.error("初始化配置文件[%s]时异常", e, item.getString());
return false;
}
}
}
return true;
}
/** 初始化监听 */
private static boolean registerMonitor()
{
//启动监视命令线程
int port = Z.conf().getPort();
if (port < 1 || port > 65535)
{
log.error("配置文件[boot.port]不是正确的端口");
return false;
}
return new ZhiqimMonitor(port).open();
}
/** 初始化框架级ClassLoader */
private static boolean createClassLoader(boolean development)
{
ClassLoader parent = Thread.currentThread().getContextClassLoader();
if (parent == null)
parent = Zhiqim.class.getClassLoader();
if (parent == null)
parent = ClassLoader.getSystemClassLoader();
//创建框架级ClassLoader,并设置到全局和当前上下文中
zClassLoader = new ZhiqimClassLoader(parent, development);
Thread.currentThread().setContextClassLoader(zClassLoader);
try
{
if (!zClassLoader.open())
{
log.error("初始化类加载器时失败");
Closes.closeIgnoreException(zClassLoader);
return false;
}
return true;
}
catch(Exception e)
{
log.error("初始化类加载器时异常", e);
Closes.closeIgnoreException(zClassLoader);
return false;
}
}
/** 初始化服务列表 */
private static boolean createServices()
{
if (!Z.conf().hasGroup(Z_SERVICE))
return true;
try
{
Group group = Z.conf().group(Z_SERVICE);
for (Item item : group.list())
{
if (!openService(item.getKey()))
return false;
}
return true;
}
catch (Exception e)
{
log.error("初始化创建服务时异常,退出工程", e);
return false;
}
}
/** 创建指定的服务 */
static boolean openService(String serviceId) throws Exception
{
Item item = Z.conf().item(Z_SERVICE, serviceId);
if (item == null)
{
log.fatal("服务[%s]配置不存在");
return false;
}
String serviceClassName = item.getString();
String serviceLoaderValue = Z.conf().getString(Z_SERVICE_LOADER, item.getKey());
if (Validates.isEmpty(serviceLoaderValue))
{//无需创建classLoader
return loadService(serviceId, serviceClassName, zClassLoader);
}
else
{//需要创建classLoader
ZhiqimClassServiceLoader serviceLoader = new ZhiqimClassServiceLoader(zClassLoader, serviceId, serviceLoaderValue);
if (!serviceLoader.open())
{//打开加载器失败
serviceLoader.close();
return false;
}
try
{
Thread.currentThread().setContextClassLoader(serviceLoader);
return loadService(serviceId, serviceClassName, serviceLoader);
}
finally
{
Thread.currentThread().setContextClassLoader(zClassLoader);
}
}
}
/** 加载服务 */
private static boolean loadService(String serviceId, String serviceClassName, ClassLoader serviceLoader) throws Exception
{
Object obj = Z.cls().newInstance(serviceClassName);
if (obj == null)
{
log.fatal("服务[%s]未找到该类", serviceClassName);
return false;
}
if (!(obj instanceof Service))
{
log.fatal("服务[%s]未实现Service接口,退出工程", serviceClassName);
return false;
}
Service service = (Service)obj;
service.setId(serviceId);
service.setClassLoader(serviceLoader);
//先放置到全局服务中,后创建,有利于服务运行中即可从全局中获取服务
Z.serv().add(service);
if (!service.create())
{
log.fatal("服务[%s]创建失败", serviceClassName);
return false;
}
return true;
}
/** 关闭服务 */
static boolean closeService(String serviceId)
{
Service service = Z.serv().get(serviceId);
if (service == null)
{
log.error("服务["+serviceId+"]不存在或未在系统中加载");
return false;
}
try
{
ClassLoader classLoader = service.getClassLoader();
if (!(classLoader instanceof ZhiqimClassServiceLoader))
{
service.destroy();
}
else
{
ClassLoader currLoader = Thread.currentThread().getContextClassLoader();
try
{
Thread.currentThread().setContextClassLoader(classLoader);
service.destroy();
((ZhiqimClassServiceLoader) classLoader).close();
}
finally
{
Thread.currentThread().setContextClassLoader(currLoader);
}
}
Z.serv().remove(serviceId);
System.gc();
log.info("服务["+serviceId+"]关闭成功");
return true;
}
catch (Exception e)
{
log.error("服务["+serviceId+"]关闭异常", e);
return false;
}
}
/** 加载类短别称,公开的原因是单元测试时方便加载./bin目录的别名 */
public static boolean loadClassAliasName(List<String> pathList)
{
FilterHandler handler = new FilterHandler()
{
@Override
public boolean handle(Object obj) throws Exception
{
String className = null;
Object[] objs = (Object[])obj;
if (objs[0] instanceof File)
{
File classPath = (File)objs[0];
File classFile = (File)objs[1];
className = Files.getClassName(classPath, classFile);
}
else
{
JarEntry jarEntry = (JarEntry)objs[1];
className = Jars.getClassName(jarEntry);
}
return addClassAlias(className) != null;
}
};
return Resources.scanClassPath(Filters.CLASS, handler, pathList);
}
/**
* 通过全称类,找到短名类注解,设置短名类名称和类结构到全局变量中
*
* @param className 类全称
*/
static String addClassAlias(String className)
{
RE<Class<?>> result = Classes.name(className);
if (!result.success())
{
log.error("检查到类[%s]加载失败[类不存在或类的静态属性初始化失败]", result.exception(), className);
return null;
}
Class<?> cls = result.value();
if (cls.isAnnotationPresent(AnGlobal.class) && cls.isAnnotationPresent(AnNew.class))
{
log.error("[%s]不能同时定义成[AnGlobal]和[AnNew]注解,两者只允许一个", className);
return null;
}
String alias = Annotations.getClassAlias(cls);
if (alias == null)
return _EMPTY_;
Class<?> has = Z.cls().get(alias);
if (has != null)
{
log.error("[%s]和[%s]的简称[%s]不允许相同", className, has.getName(), alias);
return null;
}
Z.cls().add(alias, cls);
return alias;
}
/** 获取框架类加载器 */
public ZhiqimClassLoader getZhiqimClassLoader()
{
return zClassLoader;
}
}