运行时:BusinessBaseController 及相关组件
xlyEntry/src/main/java/com/xly/web/businessweb/ 是元数据驱动运行时所在位置。本页是维护人员理解大部分通用表单运行时 controller 和 service 的地图。
承重 controller
| 类 | 包 | 角色 | 最常引用端点 |
|---|---|---|---|
BusinessBaseController |
web/businessweb/ |
元数据驱动模块的通用 CRUD。每个表单的默认 API surface。 |
/business/getModelBysId/{moduleId}、/business/getBusinessDataByFormcustomId/{formId}、/business/addUpdateDelBusinessData、/business/getSelectDataBysControlId/{controlId}
|
BusinessConfigformController |
web/businessweb/ |
已有表单的每用户 / 每组显示定制,不是基础表单定义 CRUD。 |
/configform/getConfigformData/{moduleId}、/configform/sHandleConfigform、/configform/sCopyConfigform
|
GdsmoduleController |
web/systemweb/ |
builder 侧使用的模块树和模块定义 CRUD。 |
/gdsmodule/getModuleTreePro、/gdsmodule/addGdsmodule、/gdsmodule/updateGdsmodule
|
GdsconfigformController |
web/systemweb/ |
form-master 和 form-slave 元数据 CRUD。 |
/gdsconfigform/* 下端点 |
GdsconfigtbController |
web/systemweb/ |
虚拟表 master / slave 元数据 CRUD。 |
/gdsconfigtb/* 下端点 |
BusinessTreeGridController |
web/businessweb/ |
树表格端点。当前分支实现了 proc-backed 路径,普通 getTreeGrid service 方法仍是 stub。 |
/treegrid/getTreeGridByPro/{formId} |
GenericProcedureCallController |
web/businessweb/ |
按名称 + 参数通用调用存储过程。 | /procedureCall/doGenericProcedureCall |
ConfigformPanelController |
web/businessweb/ |
gdsconfigformpanel 中的面板布局持久化。 |
/panel/get/{sFormId}、/panel/save/{sFormId}
|
CheckFlowController |
web/businessweb/ |
Activiti 工作流 surface(审批 / 驳回 / 查看),仅在部署工作流时有意义。 |
/checkFlow/* 下端点 |
注意 controller 分布在两个包中:businessweb/ 承载运行时端点,systemweb/ 承载 builder 侧元数据 CRUD 端点。两者都编译进同一个 xlyEntry WAR。
四表读取
对任何元数据驱动模块,请求生命周期(见概念 → 请求生命周期)可归结为:
public Map<String, Object> getModelBysId(Map<String, Object> map) {
List<Map<String, Object>> formList = this.getModelConfigByModleId(map); // 1. join gdsmodule⋈form-master⋈form-slave
List<Map<String, Object>> fList = businessGdsconfigformsService.getFormconstData(qMap); // 2. gdsformconst
List<Map<String, Object>> jList = businessGdsconfigformsService.getJurisdictionData(qMap); // 3. gdsjurisdiction(ADMIN 跳过)
Map<String, Object> billnosettingMap = businessGdsconfigformsService.getBillnosettingData(param); // 4. sysbillnosettings
List<Map<String, Object>> reportList = printReportService.getReportData(qMap); // 5. sysreport
return composite(formList, fList, jList, billnosettingMap, reportList);
}
先读 BusinessBaseServiceImpl.java 中这个方法;运行时其余部分都是它的变体。
返回的五键复合体
| Key | 来源 | 前端用途 |
|---|---|---|
formData |
gdsmodule ⋈ gdsconfigformmaster ⋈ gdsconfigformslave(+ 覆盖) |
表单布局 |
gdsformconst |
gdsformconst |
表单级常量、下拉标签 |
gdsjurisdiction |
gdsjurisdiction |
按钮 / 数据权限 |
billnosetting |
sysbillnosettings |
单据编号规则 |
report |
sysreport |
打印模板 |
保存端点
POST /business/addUpdateDelBusinessData 把新增 + 更新 + 删除打包为一个事务批次。前端为每行提供 sTable 和 column map:
{
"addData": [{"sTable": "<table>", "column": {"sId": "", "...": "..."}}],
"updateData": [{"sTable": "<table>", "column": {"sId": "", "...": "..."}}],
"delData": [{"sTable": "<table>", "column": {"sId": "", "...": "..."}}]
}
当 gdsmodule.sSaveProName 为空时,框架默认 Add/Update 路径运行,即 AddDelUpdCommonServiceImpl.java。非空时,调用指定存储过程。
多租户边界
每个 controller 方法的第一条非平凡语句都是:
RequestAddParamUtil.me().addParams(params, userInfo);
这是把用户 session 身份(sBrandsId、sSubsidiaryId、sBrId、sSuId、sLoginId、sLanguage、sTeamId、sMachineId 及其他 key)注入下游 params map 的单点。任何引用 #{sBrandsId} / #{sSubsidiaryId} 的 MyBatis 查询或存储过程调用都会从这里自动获得作用域。
新的 controller 方法如果不调用 RequestAddParamUtil,就是多租户 bug。
需要审计的安全关注点
-
addUpdateDelBusinessData中的sTable校验。 前端直接命名目标表。运行时必须交叉检查传入表是否属于该表单授权的支撑表,否则是权限提升面。若不存在检查,应作为安全 ticket 提出。见切片 1 v2 follow-up。 -
ADMIN 绕过权限。
BusinessBaseServiceImpl对UserType.ADMIN完全跳过gdsjurisdiction加载。ADMIN 账号治理必须来自应用外部。
缓存失效
后台保存元数据变更时会触发 JMS 消息,xlyErpJmsConsumer 中的 ConsumerChangeGdsModuleThread 会清除每个运行节点上的元数据缓存。见元数据变更后的缓存失效。