文档编号:PT-TR-configuration
PTF3 配置管理使用手册
PTF3 Configuration Architect Document
V3.0
初始版发行时间: 2004/06/01
蓬天信息系统(北京)有限公司
技术研发部
目录
AbstractManagerAgent实例(以Command配置为例) 6
AbstractMappingLoad实例(以Command配置为例) 8
AbstractParse实例(以Command配置为例) 11
AbstractManagerAgent实例(以Velocity配置为例) 12
AbstractMappingLoad实例(以Velocity配置为例) 13
AbstractParse实例(以Velocity配置为例) 15
文档描述信息:
文件名: | PTF3 Configuration规范的使用文档 |
最新版本: | V3.0 |
文档创建者: | 蓬天公司技术研发部 |
文档维护者: | 组织:蓬天公司技术研发部 成员:原力、陈永辉,任民 |
文档评审者: | 蓬天公司技术研发部、西安地税项目组 |
定稿日期: | 2004-06-01 |
文档目标: | 此文档从理论根据,概念,特征,实例的角度描述了PTF3 Cofiguration的技术细节以及开发时的接口和使用 |
文档修改摘要:
版本 | 日期 | 修改描述 | 作者 |
V3.0 | 2004-06-01 | PTF3 Cofiguration规范的使用文档 | 原力 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PTF Configuration是PTF3的新核心,其使用了插件技术进行Configuration的扩展和管理,Configuration主要包含:
一个全局注册表:
Registery
三个父类:
AbstractMappingAgent
AbstractMappingLoad
AbstractMappingParse
一个容器规范:
xxxxable extends HashMap
通过三个父类的继承和实现,以及自定义Configuration数据容器,可以针对相应的配置项管理到注册表中,同时提供有针对性的查询和访问方式。
1、 Configuration的数据由注册表来管理
2、 Configuration是单子访问的,其常驻内存
3、 Configuration由核心CfgMapping管理器来管理扩展的配置插件
4、 Configuration支持对异型配置文件的管理方式,例如xml,properties,txt等文件
5、 Configuration容许对解析文件的完整性校验,对XML文件有效
6、 Configuration支持对各种存储方式的文件的访问,例如目录,文件,压缩文件,流等
7、 Configuration可以使用一个树状结构的文件系统来填充具体的Mapping容器,例如一个Jar中文件的文件树
8、 Configuration中存储的单个元素必须是唯一的
9、 Configuration提供可以扩展的注册表查找方式
Configuration是一个开放的架构体系所必须的组件,也可以说Configuration是一个架构体系的核心组件,这是因为在开放的机构中,各种组件相互直接都相对独立,它们实际是使用一直可配置的Configuration管理器来相互作用。这就是Configuration的核心所在:组件一个可扩展的由配置器组织的框架结构。
Configuration在PTF2中使用了曾经使用过两种技术实现:
1. Mapping容器 这个方式是在内存中管理一个单子的Mapping,相当于注册表,在此注册表中按Domain存放注册项,这个概念的模型是完善的,但在实现中,由于使用了硬编码,造成Configuration的扩展和访问困难,Configuration被局限在一个狭小的应用层面上。
2. JMX Configuration在PTF2中还完整的使用JMX实现了符合JMX规范的Configuration,这种方式虽然可以实现动态的管理配置对象的各种属性,但由于其管理方式和应用的组件较多而放弃
3. 现在Configuration的实际采用了Mapping容器模式,在实现上,分离了注册表,解析器底层,和Domain容器这个几个层面,同时实现了一种自我管理的插件模式的Configuration管理器
一个全局注册表:
Registery: 注册表是一个全局的单子容器,其需要在启动时进行初始化
三个父类:
AbstractManagerAgent: 是Configuration的Manager Agent的抽象类
Manager Agemt是Configuration的主控制器,从指定的
Configuration 注册相应类型Map项中获得指定的属性.
AbstractMappingLoad: 是Configuration中Mapping解析的Load程序接口
本程序支持以下方法的文件访问.
在压缩文件中所有文件.
在物理目录中的所有文件.
单独文件.
单独文件流
AbstractParse: 是Configuration进行配置或外部数据解析的抽象类
一个容器规范:
xxxxable extends HashMap: 是继承HashMap用于存放配置元素的容器,其将按照Domain注册到注册表中
API说明
(见PTF3javadoc中com.ptf.cfg和com.ptf.mapping包部分)
1、xxxable必须继承HashMap和serializable
2、对Configuration的访问必须使用REGISTRY_NAME=”xxxxx”来声明访问注册表的Domain,不进行声明回出现ClassCastException异常
3、对于具体的Agent,用户可以自定义配置元素的查询方法,用于自定义环境
4、多个Agent可以用于解析一个XML的各个部分,也就是说,不是一种类型的XML对于一个Agent,Agent是按照逻辑类型分类的,而XML是实际的数据存储类
基于xml文件的配置管理,需要具体的解析过程,这是因为xml文件是一个复杂的结构文档。必须按照用户自定义的需求进行具体解析。
多个Agent可以用于解析一个XML的各个部分,也就是说,不是一种类型的XML对于一个Agent,Agent是按照逻辑类型分类的,而XML是实际的数据存储类
基于HashMap的配置数据容器
/** * Command Config数据容器,继承了HashMap并实现了Serializable接口 */ public class CmdConfigable extends HashMap implements Serializable { /** CmdConfigable对象的构造器 */ public CmdConfigable() { }
/** * 根据名称获得Command Config *@param name 参数描述 *@return the SqlNamedQuery value of sqlNamedQuery. */ public CommandsConfig getCommandsConfig(String name) { return (CommandsConfig)this.get(name); }
/** * 向容器中新增Command Config *@param name 新增属性 CmdConfig的值 *@param cmdcfg 新增属性 CmdConfig的值 */ public void addCmdConfig(String name, CommandsConfig cmdcfg) { this.put(name, cmdcfg); }
/** * 新增 CommandsConfig属性到对象 CmdConfigable object * *@param name 新增属性 CommandsConfig的值 *@param form 新增属性 CommandsConfig的值 *@param cmdlist 新增属性 CommandsConfig的值 */ public void addCommandsConfig(String name, String form, List cmdlist) { CommandsConfig cfg = new CommandsConfig();
cfg.setName(name); cfg.setFormClassName(form); cfg.setCommandList(cmdlist); } } |
基于XML文件的配置管理
AbstractManagerAgent实例(以Command配置为例)
/** * Class描述 CmdConfigManagerAgent是PTF Configuration AbstractManagerAgent的子类.<BR> * CmdConfigManagerAgent完成管理Command Config配置数据到注册表的操作,并提供查询方法 */ public class CmdConfigManagerAgent extends AbstractManagerAgent { /** * 属性描述 Command Config数据容器 */ private CmdConfigable cfgable = null; /** * 属性描述 Log实例 */ private final static Logger log = Logger.getLogger(CmdConfigManagerAgent.class);
/** CmdConfigManagerAgent对象的构造器 */ public CmdConfigManagerAgent() { super(); }
/** * 获得指定Command名称的Command Config对象 * *@param name Description of the Parameter *@return The property value */ public CommandsConfig getCommandsConfig(String name) { cfgable = (CmdConfigable) registry.configContext.get(REGISTRY_NAME);
CommandsConfig cfg = null;
if (registry == null) { log.debug(" registry is null, please init registry with Registry.getRegistry() method "); } if (cfgable != null) { // log.debug(sqlable); cfg = cfgable.getCommandsConfig(name); } return cfg; }
/** * 方法描述 调用解析配置文件接口AbstractParse及其实现CmdConfigMappingParse * *@exception MappingException 异常处理 */ public void parse() throws MappingException { AbstractParse parse = new CmdConfigMappingParse();
parse.PATH = this.PATH; cfgable = (CmdConfigable) parse.getResult(); }
/** * 新增解析后的Command Config容器到注册表 */ public void addRegistry() { registry.addDomain(REGISTRY_NAME, cfgable); } } |
AbstractMappingLoad实例(以Command配置为例)
/** * Class描述 CmdConfigMappingLoad是PTF Configuration AbstractMappingLoad的子类.<BR> * CmdConfigMappingLoad完成解析Command Config配置动作,是具体的配置解析类 */ public class CmdConfigMappingLoad extends AbstractMappingLoad {
/** * 属性描述 Command Config数据容器 */ private CmdConfigable cfgable = new CmdConfigable(); /** * 属性描述 log实例 */ private static Logger log = Logger.getLogger(CmdConfigMappingLoad.class);
/** CmdConfigMappingLoad对象的构造器 */ public CmdConfigMappingLoad() { super(); //声明配置文件的后缀 descName = ".xml"; //设置是否进行XML的有效性校验 valid = false; }
/** * 获得CmdConfigable *@return the MsgMappingable value of msgable. */ public CmdConfigable getCmdConfigable() { return cfgable; }
/** * 方法描述 继承AbstractMappingLoad的add方法,向解析器中添加配置源,并进行解析,存入容器 * *@param doc 参数描述 *@exception MappingException 异常处理 */ public void add(org.dom4j.Document doc) throws MappingException { //使用Dom4J进行XML的解析 List cmdcfgs = doc.getRootElement().elements(CmdCfgContains.CMD_CFG);
if (cmdcfgs != null) { for (Iterator it = cmdcfgs.iterator(); it.hasNext(); ) { CommandsConfig cfg = new CommandsConfig(); Element cmdcfg = (Element) it.next(); String name = cmdcfg.element(CmdCfgContains.CMD_NAME).getText();
cfg.setName(name);
Element formel = cmdcfg.element(CmdCfgContains.CMD_FORM);
if (formel != null) { String form = formel.getText();
cfg.setFormClassName(form); }
Element tx = cmdcfg.element(CmdCfgContains.CMD_TXDS); String txname = CmdCfgContains.CMD_DETXDS;
if (tx != null) { txname = tx.getText(); cfg.setTxDsName(txname); }
Element cmdlist = cmdcfg.element(CmdCfgContains.CMD_LIST);
if (cmdlist != null) { Iterator cmds = cmdlist.elementIterator(CmdCfgContains.CMD); List cmdits = new ArrayList();
while (cmds.hasNext()) { Element cmd = (Element) cmds.next();
cmdits.add(cmd.getText()); } cfg.setCommandList(cmdits); } cfgable.addCmdConfig(name, cfg); } } }
/** * 方法描述 使用Dom4J的Document进行解析,本方法为伪方法 * *@param doc 参数描述 *@exception MappingException 异常处理 */ public void configure(org.dom4j.Document doc) throws MappingException { } } |
AbstractParse实例(以Command配置为例)
/** * Class描述 CmdConfigMappingParse是PTF Configuration AbstractParse的子类.<BR> * CmdConfigMappingParse完成解析Command Config配置,并存储数据到CmdConfigable */ public class CmdConfigMappingParse extends AbstractParse {
/** * 属性描述 Command Config数据容器 */ private CmdConfigable cfgable; /** * 属性描述 Log实例 */ private final static Logger log = Logger.getLogger(CmdConfigMappingParse.class);
/** CmdConfigMappingParse对象的构造器 */ public CmdConfigMappingParse() { super(); }
/** * 获得CmdConfigMappingParse object的Result属性 * 获得Command Config的所有数据 * *@return The Result value */ public Object getResult() { CmdConfigMappingLoad load = new CmdConfigMappingLoad();
try { String filename = this.PATH;
load.addJar(filename); cfgable = load.getCmdConfigable(); } catch (MappingException ex) { ex.printStackTrace(); } return cfgable; } } |
基于Properties文件的配置管理
基于Properties文件的配置管理,不需要具体的解析过程,这是因为Properties工具类直接解析了Properties类型文件,其解析器在Properties工具类内部实现,所有在这种类型文件解析时,在Parse和Load中只是实现了外部传入数据的类型定义和流处理,而没有具体的解析过程.
AbstractManagerAgent实例(以Velocity配置为例)
/** * Class描述 VcManagerAgent是PTF Configuration AbstractManagerAgent的子类.<BR> * VcManagerAgent完成管理velocity的Properties的配置数据到注册表的操作,并提供查询方法 */ public class VcManagerAgent extends AbstractManagerAgent { /** * 属性描述 Velocity数据容器 */ private Velocityable vcable = null; /** * 属性描述 Log实例 */ private final static Logger log = Logger.getLogger(VcManagerAgent.class);
/** VcManagerAgent对象的构造器 */ public VcManagerAgent() { super(); }
/** * 从指定的名称中获得Velocity的指定Properties * *@param name Description of the Parameter *@return The property value */ public Properties getVelocity(String name) { vcable = (Velocityable) registry.configContext.get(REGISTRY_NAME); if (registry == null) { log.debug(" registry is null, please init registry with Registry.getRegistry() method "); }
Properties props = null;
if (vcable != null) { // log.debug(sqlable); props = vcable.getProps(name); } return props; }
/** * 方法描述 什么AbstractParse接口的具体实现,并进行解析 * *@exception MappingException 异常处理 */ public void parse() throws MappingException { AbstractParse parse = new VcMappingParse();
parse.PATH = this.PATH; vcable = (Velocityable) parse.getResult(); }
/** * 增加解析后的数据容器到注册表 */ public void addRegistry() { registry.addDomain(REGISTRY_NAME, vcable); } } |
AbstractMappingLoad实例(以Velocity配置为例)
/** * Class描述 VcMappingLoad是PTF Configuration AbstractMappingLoad的子类.<BR> * VcMappingLoad完成解析Velocity配置动作,是具体的配置解析类 */ public class VcMappingLoad extends AbstractMappingLoad {
/** * 属性描述 Velocity数据容器 */ private Velocityable vcable = new Velocityable(); /** * 属性描述 Log实例 */ private static Logger log = Logger.getLogger(VcMappingLoad.class); /** * 属性描述 默认属性名称 */ private final static String DEFAULT_NAME = "default";
/** VcMappingLoad对象的构造器 */ public VcMappingLoad() { super(); //声明配置文件后缀 descName = ".properties"; }
/** * 获得Velocity数据容器 *@return the MsgMappingable value of msgable. */ public Velocityable getVelocityable() { return vcable; }
/** * 方法描述 增加properties对象作为数据源,名称伪默认属性 * *@param props 参数描述 *@exception MappingException 异常处理 */ public void add(Properties props) throws MappingException { vcable.addProps(DEFAULT_NAME, props); }
/** * 方法描述 增加指定名称的properties对象作为数据源 * *@param name 参数描述 *@param props 参数描述 *@exception MappingException 异常处理 */ public void add(String name, Properties props) throws MappingException { vcable.addProps(name, props); }
/** * 方法描述 Dom4J对象作为数据源,本方法为伪方法 * *@param doc 参数描述 *@exception MappingException 异常处理 */ public void add(org.dom4j.Document doc) throws MappingException { }
/** * 方法描述 使用Dom4J的Document进行解析,本方法为伪方法 * *@param doc 参数描述 *@exception MappingException 异常处理 */ public void configure(org.dom4j.Document doc) throws MappingException { } } |
AbstractParse实例(以Velocity配置为例)
/** * Class描述 VcMappingParse是PTF Configuration AbstractParse的子类.<BR> * VcMappingParse完成解析Velocity配置,并存储数据到Velocityable */ public class VcMappingParse extends AbstractParse {
/** * 属性描述 Velocity数据容器 */ private Velocityable vcable; /** * 属性描述 Log实例 */ private final static Logger log = Logger.getLogger(VcMappingParse.class);
/** VcMappingParse对象的构造器 */ public VcMappingParse() { super(); }
/** * 获得VcMappingParse object的Result属性 * *@return The Result value */ public Object getResult() { VcMappingLoad load = new VcMappingLoad();
try { String filename = this.PATH;
// log.debug(filename); if (filename.endsWith("properties")) { load.addProps(filename); } else if (filename.endsWith(".jar")) { load.addJar(filename); } vcable = load.getVelocityable(); } catch (MappingException ex) { ex.printStackTrace(); } return vcable; } } |
对Configuration的测试比较简单,主要是选择具体的Agent和对象,并按照具体的查询方法操作即可,注意,一定要声明REGISTRY_NAME注册名
/** * Configuration的测试程序,测试Configuration的初始化,和各种Agent的访问过程 * *@author 原力 *@created 2003年11月26日 */ public class CfgTest { /** * 本测试程序的主执行器方法 * *@param args The command line arguments */ public static void main(String[] args) { CfgTest cfgtest = new CfgTest(); cfgtest.parse(); }
/** * 对Cfgable数据容器的测试 */ public void cfgable() { Cfgable map = new Cfgable(); Config conf = new Config(); conf.setAlias("test"); conf.setPath("./test"); map.addCfg("com.ptf.cfg.Test.class", conf); System.out.println(map.getAlias("com.ptf.cfg.Test.class")); }
/** * 测试Configuration的初始化,和各种Agent的访问过程 */ public void parse() { //测试Configuration的初始化 ConfigurationFactory factory = ConfigurationFactory.getFactory(); factory.initRegistry(); //PTF2中的MsgManagerAgent的访问过程 com.ptf.mapping.msgptf2.agent.MsgManagerAgent agento = new com.ptf.mapping.msgptf2.agent.MsgManagerAgent(); //声明注册名 agento.REGISTRY_NAME = "msgptf2mapping"; //打印输出测试结果 System.out.println("ptf2 message<-" + agento.getNamedMessage("dossier_date_invalid")); //PTF3中的MsgManagerAgent的访问过程 com.ptf.mapping.msg.agent.MsgManagerAgent agent = new com.ptf.mapping.msg.agent.MsgManagerAgent(); //声明注册名 agent.REGISTRY_NAME = "msgmapping"; //打印输出测试结果 System.out.println("message<-" + agent.getNamedMessage("SystemException")); //PTF3中的SqlManagerAgent的访问过程 com.ptf.mapping.sql.agent.SqlManagerAgent sqlagent = new com.ptf.mapping.sql.agent.SqlManagerAgent(); //声明注册名 sqlagent.REGISTRY_NAME = "sqlmapping"; //打印输出测试结果 System.out.println("sql<-" + sqlagent.getSqlQuery("acc.hello")); //PTF2中的SqlManagerAgent的访问过程 com.ptf.mapping.sqlptf2.agent.SqlManagerAgent sqlptf2agent = new com.ptf.mapping.sqlptf2.agent.SqlManagerAgent(); //声明注册名 sqlptf2agent.REGISTRY_NAME = "sqlptf2mapping"; //打印输出测试结果 System.out.println("ptf2 sql<-" + sqlptf2agent.getSqlQuery("mytest1")); //PTF3中的VcManagerAgent的访问过程 VcManagerAgent vc = new VcManagerAgent(); //声明注册名 vc.REGISTRY_NAME = "velocity"; //打印输出测试结果 System.out.println("velocity<-" + vc.getVelocity("velocity")); } } |