# 应用包导入导出接入
# 说明
应用包的导入导出是个泛指,还包含了其他的应用定制平台下的包的导入导出。列表如下:
类型 | 来源 | 是否支持更新 |
---|---|---|
应用包 | 应用管理或者基础数据 | 是 |
表单 | 表单管理或者应用包里面的表单 | 否 |
聚合包 | 聚合应用管理 | 是 |
除了导入导出和更新外,应用包(仅限应用包)还支持一种特殊操作:合并导入。可以将一个不相干的应用包的部分或者全部数据导入当前选择的应用包,类似于应用包合并。
# 导入导出上下文
导入导出的上下文类是BusinessDataBean,定义在cap-api这个工程。主要的属性说明如下:
属性 | 存在场景(*表示全部) | 说明 |
---|---|---|
bizConfigBean | 应用包和聚合包导入导出 | 当前导入或导出的应用包 |
appUpgradeCacheBean | 全部 | 需要入库的数据,包含了businessDateBean的大部分功能 |
upgradeSourceApp | 应用包或聚合包更新 | 被更新的应用包 |
upgradeSourceFormMap | 应用包或聚合包更新 | 被更新的表单列表 |
exportType | * | FORM为表单导入导出,APPLICATION为应用包导入导出 |
importFormType | 表单导入 | 0:保留原类型;1:有流程;2:无流程 |
upgrade | 更新场景 | true表示应用包更新 |
formBeanList | * | 导入的表单列表 |
isMallApp | 应用包场景 | 是否是商品包 |
rootMap | * | 最终要写入应用包的数据或者从应用包读取的数据 |
extensionMap | * | 最终要写入应用包的扩展数据或者从应用包读取的扩展数据 |
hasBaseData | 应用包或者聚合包导入 | 是否有基础数据 |
capAppSetupBizMapping | * | id映射表,后面专门解释 |
# 接口说明
要接入应用包导入导出,一般来说,从一下两个抽象类实现其中一个即可
类名 | 所在工程 | 说明 |
---|---|---|
AbstractBusinessModuleExportManager | cap-api | 应用包下级模块或者基础模块的数据导入导出,类似报表,关联触发等 |
AbstractBusinessFormExportManager | cap-core | 表单下级模块的数据导入导出接口,类似明细表,应用绑定等 |
这里要注意选择合适的接口,两个类的方法参数会有细微区别
# 方法说明
公共参数说明
businessDataBean 是应用包导入导出的上下文,在导入导出的时候可以将自己的数据存在该上下文,然后再不同的阶段使用
FormBean 表单的对象类,只有AbstractBusinessFormExportManager类方法有该参数,表示当前正在处理的表单,所以需要注意的是这个表单数据不一定是完整的。
appUpgradeCacheBean:入库数据,在importdata方法执行的时候,将要入库的数据放在该类中,最后入库的时候使用
AbstractBusinessModuleExportManager方法说明
方法 | 参数 | 说明 |
---|---|---|
exportData | rootMap表单要写入包文件的数据,所以要导出的数据需要添加到该map | 数据导出 |
importData | 表示从应用包中读取的包原始数据,需要查询自己的数据并解析 | 数据导入 |
exportEnums | 枚举导出,一些特殊场景会使用没有在表单绑定的枚举,这些枚举需要在这个方法统一处理,否则导入时候可能会丢失 | |
compatibilityDetection | CompatibilityDetectionResultBean表示不兼容的属性集合 | 在应用包更新的时候,需要对部分特殊无法更新的数据检测,如果这些数据发生了变更,则阻断更新,并提示用户 |
upgradeDataCompare | UpgradeCompareResultBean发生更新的属性说明 | 应用包更新场景下,需要对更新的数据做出描述,在这个方法处理,并将结果放入参数中 |
redirectBusiness | businessRedirectDataBean | 当前模块使用了组织架构的数据的话,需要对组织架构数据进行重定向,这个方法就是用来获取当前模块中所有组织架构数据的 |
mergeRedirectData | redirectData表示客户重定向的组织架构数据 | 客户重定向操作执行后会将组织架构的映射信息传入当前方法,开发就可以更新当前模块的组织架构信息 |
completeSetup | appUpgradeCacheBean | 数据入库 |
cancelSetup | 取消安装,模块需要清理下缓存以及临时数据 |
AbstractBusinessFormExportManager方法说明。表单数据在循环处理时,会调用以下方法
方法 | 参数 | 说明 |
---|---|---|
exportData | formDataMap表示要导出的表单数据 | 导出表单数据,开发在处理好要导出的数据后,放于formDataMap即可 |
importData | dataMap从应用包读取的表单数据 | 导入表单数据,开发将参数中的dataMap处理成要入库的数据,存放formbean中 |
compatibilityDetection | 同应用包,newFormBean表示包里的表单,cacheFormBean表示id相同的被更新的表单 | 更新场景下兼容性检测,同应用包 |
upgradeDataCompare | 同上 | 更新场景下获取更新说明,同应用包 |
redirectForm | 同应用包redirectBusiness | 同应用包redirectBusiness |
mergeRedirectData | 同应用包 | 同应用包 |
completeSetup | 同应用包 | 同应用包 |
cancelSetup | 同应用包 | 同应用包 |
# 常用的导包场景判断
方法 | 说明 |
---|---|
businessDataBean instanceof MergeSetupContext | 是否是业务包合并的场景 |
businessDataBean.isSetup() | true为安装,false为导出 |
businessDataBean.isUpgrade() | true是更新场景 |
businessDataBean.isFormSetup() | true为表单导入 |
# 应用包重复安装
什么是业务包重复安装?
就是一个业务包可以在同一个V5里面多次导入,但是导出后还可以互相更新。
举个例子:我在a82环境创建了一个应用包“合同管理”,我把这个应用包导出成syz文件,然后再导入a82,就会生成一个新的应用包“合同管理”,我把新的合同管理
导出来成syz,去更新最开始创建的哪个应用包,是可以更新成功的。再次新建一个应用包“合同应用”,导出后更新之前的包会提示不是同一个应用包,无法更新。
所以就会存在一个问题,同一个应用包导入了两次,id肯定不能相同,但是id不相同的话又怎么互相更新呢?
当前的解决方案是id映射,第一个合同管理的id是 345,在导出的时候会产生一个映射id345,再次导入的时候会生成一个随机的uuid例如123,同事建立123到345的映射,在123导出的时候,会把id重新还原成345,这样更新的时候就能判断是一个应用包。
上面说的生成映射和还原映射的方法在businessDatabean中已经提供。
还原id的方法(导出时候用)
方法 | 说明 |
---|---|
lookupBizKey(MappingTable table, Long sourceId) | 用作应用包,表单,枚举,常量这四种类型的数据id的还原,MappingTable对应这四种类型,sourceId为当前的业务id。 |
lookupBizKey(MappingField field, Long sourceId, Long dataId) | 用做应用包,表单下的子级的数据还原数据id,MappingField具体数据可以参考这个,根据ownerTable数据判断sourceId传入什么参数,例如视图的id替换,使用如下方式:businessDataBean.lookupBizKey(BusinessEnums.MappingField.VIEW_ID_MAPPING, formBean.getId(), viewId)) |
创建或者查询id的的方法(导入用)
方法 | 说明 |
---|---|
generateOrGetRootId(MappingTable table, Long bizKey) | 根据包里面的id创建或者生成一个id,已经生成的就返回,没有的话就创建一个 |
generateOrGetSubId(MappingField field, Long sourceId, Long bizKey) | 根据包里面的id创建或者生成一个子级id。例如: businessDataBean.generateOrGetSubId(BusinessEnums.MappingField.VIEW_ID_MAPPING, formId, viewId) |
onlyGetRootId(MappingTable table, Long bizKey) | 查询已经生成的id,没有的话返回null |
onlyGetSubId(MappingField field, Long sourceId, Long bizKey) | 查询已经生成的子级id,没有的话返回null:例如:businessDataBean.onlyGetSubId(BusinessEnums.MappingField.VIEW_ID_MAPPING, formId, viewId) |
除此之外,还有一些特殊方法:
方法 | 说明 |
---|---|
findEnumItemId | 查询枚举id的映射id,导入用 |
circulateFindId(Long sourceId, Boolean setup) | 获取传入id的映射id,setup控制导入还是导出,慎用 |
注意:我们在处理id的时候不只是处理自己的数据的id,自己数据引用数据的id也要同步处理,不然导入的时候可能会丢失数据。例如我要处理一个计算公式,计算公式使用了枚举,这个计算公式的id要替换,计算公式中的枚举id也要替换。
# 数据处理
有些数据需要用户处理后才能入库,目前导入导出对这部分的支持比较弱,需要业务方与前端自行沟通,增加接口处理客户返回的数据。导入导出能提供的能力如下:
# 返回数据到前端
com.seeyon.cap4.form.modules.importandexport.BusinessDataBean#getResultMap();
com.seeyon.cap4.form.modules.importandexport.AppUpgradeCacheBean#getResultMap();
通过上面的方式获取到Map后,将要展示的数据放在这个map中即可,注意放入的数据需要实现Serializable接口.
至于key,和前端同事商量一致即可。
# 获取应用安装上下文
客户处理完处理后,需要业务方自己添加接口处理客户的数据,这个时候是需要业务上下文的。可以通过如下方式获取:
Long bizConfigId = ParamUtil.getLong(params, "bizConfigId", 0L);
final AppUpgradeCacheBean appUpgradeCacheBean = businessImportAndExportManager.getAppUpgradeCacheBean(bizConfigId.toString());