# 产品区隔组件
# 开场问题
V8.1版本有A6+、A8+、A8-N、G6+、G6-N、G6-SU这么多产品线,其中A8+还有企业版和集团版之分,A8-N/G6+/G6-N/G6-SU还有同义的单组织和多组织之分。
这里提出两个开场问题:
- 这么多产品线,我们在代码中是如何版本管理的?
- 这么多产品线,肯定有功能的区隔(比如A6+和A8+都有致信功能,产品设计上要求致信在不同产品线上显示不同的图标,这个应该如何实现才利于维护?)
基于上面两个问题,V5提供了ProductEditionEnum和SysFlag的实现来解决问题。
# 版本定义文件ProductEditionEnum
com.seeyon.ctp.common.constants.ProductEditionEnum是版本定义文件,基本代码实现如下:
public enum ProductEditionEnum {
a6 (0, "A6V5-1", "edition.a6.product", ""), // A6+版
enterprise (1, "A8V5-1", "edition.enterprise.product", ""), // A8+企业版
entgroup (2, "A8V5-2", "edition.entgroup.product", ""), // A8+企业集团版
government (3, "G6V5-1", "edition.government.product", ".GOV"), // 政务版
governmentgroup (4, "G6V5-2", "edition.governmentgroup.product", ".GOV"), // 政务多组织版
a8n1 (14, "A8NV5-1", "edition.a8n1.product", ""), // A8-N企业版
a8n2 (15, "A8NV5-2", "edition.a8n2.product", ""), // A8-N企业集团版
g6n1 (16, "G6NV5-1", "edition.g6n1.product", ".GOV"), // G6-N单组织版
g6n2 (17, "G6NV5-2", "edition.g6n2.product", ".GOV"),// G6-N多组织版
g6su1 (18, "G6SUV5-1", "edition.governmentsupervision.product", ".GOV"), // G6-督查督办单组织版
g6su2 (19, "G6SUV5-2", "edition.governmentsupervisiongroup.product", ".GOV") // G6-督查督办多组织版
;
......
}
我们可以通过ProductEditionEnum.getCurrentProductEditionEnum()方法获取到当前正在使用的协同产品线:
int productId = ProductEditionEnum.getCurrentProductEditionEnum().key;
那么,你可能还有个问题:系统是怎么知道我当前正在使用的产品线的?
我们对产品线进行了多重描述:产品线定义文件+产品描述文件+数据库标记+加密狗文件。以后在开发分析问题的时候,可以通过如下方式去了解客户产品线
产品线定义文件存放于:ApacheJetspeed\webapps\seeyon\common\js\ui\publicinfomenu.js
产品描述文件存放于:ApacheJetspeed\webapps\seeyon\WEB-INF\cfgHome\base\productFeature.xml
# 功能区隔组件SysFlag
那么回到开场问题:比如A6+和A8+都有致信功能,产品设计上要求致信在不同产品线上显示不同的图标,这个应该如何实现才利于维护?
那么,我们开发可能会考虑基于currentProductEdition就能用来做功能区隔:
int currentProductId= ProductEditionEnum.getCurrentProductEditionEnum().getKey();
if(currentProductId == ProductEditionEnum.a6.getKey()) {
}else {
}
可以明确的是:上面这段代码在当前版本是有效的。但是如果下个版本又出现了b6+、c6+的产品线,同样需要做屏蔽怎么办?
如果我们代码中有几十上百处都这样来处理,那么下个版本就要修改几十上百处的代码,对代码的可维护性太差!
基于可维护的问题,平台提供了SysFlag工具类。
# SysFlag的用法
倒过来介绍,先介绍如果在SysFlag中定义了必要的方法之后,我们会怎么改写上面的代码:
boolean ucEnabled = (boolean) SysFlag.ucEnableButton.getFlag();
上面这一句简单代码即可实现enable功能,SysFlag.ucEnableButton的实现代码如下:
public enum SysFlag {
/***************************************************************************
* 开发人员定义的代码在这里 参数顺序依次是:A6-s-V5, A6-V5, A8企业版标志、A8企业集团版、政务版标志、政务多组织版、UFIDA-NC套件版标志、cwork
*/
sys_isGroupVer(false, false, false, true, false, true, true, false), //是否为多组织版本
sys_isEnterpriseVer(false, false, true, false, false, false, false, false), //是否为企业版本
sys_isGovVer(false, false, false, false, true, true, false, false), //是否为政务版本(含政务版和政务多组织版)
sys_isA6Ver(true, true, false, false, false, false, false, false), //是否为A6
sys_isG6S(false, false, false, false, false, false, false, false), //是否为G6-s
ucEnableButton(false, false, true, true, true, true, true, true), // 致信屏蔽A6+特性
}
上面代码的释义:枚举下面每个参数代表一个产品线,第二个参数代表A6+,第三个代表A8企业版,第四个代表A8集团版,通过不同参数true、false控制就能来确定什么产品线支持什么功能。
综上,如果要基于产品线屏蔽某个功能特性,开发只需要在SysFlag下面新增一个枚举,针对对应产品线设置标识语句即可。
当然,如果需要不同产品线使用不同的图标,还可以直接在SysFlag中定义图标文件名,在代码中直接调用即可:
IconSuffix("abouta6.png", "abouta81.png", "abouta82.png", "default.png", "default.png", "default.png", "default.png", "default.png")
# SysFlag的实现原理
SysFlag的实现原理很简单:就是初始化的时候就内置了当前产品线,随后在调用SysFlag枚举的时候已经能定位到对应枚举变量了,代码如下:
public enum SysFlag {
/***************************************************************************
* 开发人员定义的代码在这里 参数顺序依次是:A6-s-V5, A6-V5, A8企业版标志、A8企业集团版、政务版标志、政务多组织版、UFIDA-NC套件版标志、cwork
*/
ucEnableButton(false, false, true, true, true, true, true, true), // 致信屏蔽A6+特性
;
private Map<ProductEditionEnum, Object> flags = new EnumMap<ProductEditionEnum, Object>(ProductEditionEnum.class);
SysFlag(Object a6sFlag, Object a6Flag, Object enterpriseFlag, Object entgroupFlag, Object governmentFlag, Object governmentgroupFlag, Object ufidancFlag, Object cworkFlag) {
flags.put(ProductEditionEnum.a6s, a6sFlag);
flags.put(ProductEditionEnum.a6, a6Flag);
flags.put(ProductEditionEnum.a6p, a6Flag);
flags.put(ProductEditionEnum.enterprise, enterpriseFlag);
flags.put(ProductEditionEnum.a8n1, enterpriseFlag);
flags.put(ProductEditionEnum.entgroup, entgroupFlag);
flags.put(ProductEditionEnum.a8n2, entgroupFlag);
flags.put(ProductEditionEnum.government, governmentFlag);
flags.put(ProductEditionEnum.governmentgroup, governmentgroupFlag);
flags.put(ProductEditionEnum.ufidanc, ufidancFlag);
flags.put(ProductEditionEnum.cwork, cworkFlag);
flags.put(ProductEditionEnum.g6n1, governmentFlag);
flags.put(ProductEditionEnum.g6n2, governmentgroupFlag);
flags.put(ProductEditionEnum.g6su1, governmentFlag);
flags.put(ProductEditionEnum.g6su2, governmentgroupFlag);
}
/**
* 取得标志,自动识别版本
*
* @return 对应版本的标志
*/
public Object getFlag() {
return flags.get(currentProductEdition);
}
//产品版本.
private static ProductEditionEnum currentProductEdition = null;
static{
currentProductEdition = ProductEditionEnum.getCurrentProductEditionEnum();
}
}