Appearance
钩子方法参考
🪝 钩子详解:Basic继承体系中所有钩子方法的完整说明,必须遵循Basic继承指南规范
📋 目录
钩子方法概述
什么是钩子方法?
钩子方法是Basic继承体系提供的扩展点,允许在特定的操作节点插入自定义的业务逻辑。
⚠️ 重要:必须使用正确的导入路径
在使用钩子方法时,必须确保所有相关类使用项目正确的包路径:
java
// ✅ 正确的导入路径
import jpwise.util.UserProvider; // 用户提供者
import jpwise.model.base.UserInfo; // 用户信息
import jpwise.model.flow.FlowTaskEntity; // 工作流任务实体
import jpwise.engine.model.flowengine.FlowModel; // 工作流模型
import jpwise.base.enums.FlowRecordEnum; // 工作流记录枚举
import jpwise.util.JsonUtil; // JSON工具类
import jpwise.util.DateUtil; // 日期工具类
import jpwise.util.StringUtil; // 字符串工具类
import jpwise.util.RandomUtil; // 随机工具类
import jpwise.exception.BusinessException; // 业务异常
import jpwise.exception.DataException; // 数据异常
⚠️ 常见错误:使用错误的包路径会导致编译失败或运行时异常。
📋 快速开始模板
java
@Slf4j // ✅ 必须添加
@Service
@UseDataSource(DbNameConst.JPWISE_DEMO)
public class YourServiceImpl extends BasicDemoServiceImpl<YourMapper, YourEntity>
implements YourService {
@Autowired
private UserProvider userProvider;
// 只添加实际需要的钩子方法
}
### 🔥 核心编码规范(必须遵循)
1. **Entity优先原则** - 转换为Entity对象进行类型安全操作
2. **避免双重操作** - 不要同时修改entity和dic
3. **统一转换** - 最后用JsonUtil.entityToMap()转换回dic
4. **按需添加** - 只有用户明确需要时才添加对应钩子方法
5. **调用super方法** - 钩子方法中必须调用父类方法
### 钩子方法分类
- **数据操作钩子** - 保存、删除等操作的前后处理
- **子表操作钩子** - 主子表数据的协调处理
- **工作流钩子** - 工作流各个环节的业务处理
- **数据获取钩子** - 查询数据的后处理
---
## 数据操作钩子
### beforeSave - 保存前处理
**时机**:数据保存到数据库之前
**用途**:数据验证、字段补全、业务规则检查
```java
@Override
public Map<String, Object> beforeSave(Map<String, Object> dic, Boolean isNew)
throws BusinessException, DataException {
// ✅ 正确:转换为Entity对象进行类型安全操作
MyEntity entity = JsonUtil.getJsonToBean(dic, MyEntity.class);
if (isNew) {
// 新增时的处理 - 只操作entity对象
if (StringUtil.isEmpty(entity.getCODE())) {
// 生成业务编号
entity.setCODE(generateBusinessCode());
}
// ✅ 正确:避免硬编码常量,使用方法获取
entity.setSTATUS(getDefaultStatus());
// 设置申请人信息
UserInfo userInfo = userProvider.get();
entity.setAPPLICANTNAME(userInfo.getUserName());
} else {
// 更新时的处理
if (!getDraftStatus().equals(entity.getSTATUS())) {
throw new BusinessException("只有草稿状态的记录才能修改");
}
}
// 业务规则验证
validateBusinessRules(entity);
// 数据完整性检查
if (StringUtil.isEmpty(entity.getTITLE())) {
throw new BusinessException("标题不能为空");
}
// ✅ 正确:最后统一转换回dic,避免同时操作entity和dic
Map<String, Object> result = JsonUtil.entityToMap(entity);
result.putAll(dic); // 保留原有的其他字段
return super.beforeSave(result, isNew);
}
private void validateBusinessRules(MyEntity entity) {
if (entity.getAMOUNT() != null && entity.getAMOUNT().compareTo(getMaxAmount()) > 0) {
throw new BusinessException("金额不能超过限制");
}
}
❌ 错误示例 - 避免这样写:
java
@Override
public Map<String, Object> beforeSave(Map<String, Object> dic, Boolean isNew) {
MyEntity entity = JsonUtil.getJsonToBean(dic, MyEntity.class);
// ❌ 错误:同时修改entity和dic(重复操作)
entity.setCODE("NEW001");
dic.put("CODE", "NEW001"); // 重复操作
return super.beforeSave(dic, isNew);
}
常用场景:
- 生成业务编号
- 设置默认值
- 数据验证
- 权限检查
- 重复数据检查
afterSave - 保存后处理
时机:数据成功保存到数据库之后
用途:发送通知、更新缓存、记录日志、触发其他业务
java
@Override
public Map<String, Object> afterSave(Map<String, Object> dic, Boolean isNew)
throws BusinessException, DataException {
// ✅ 正确:转换为Entity对象进行类型安全操作
MyEntity entity = JsonUtil.getJsonToBean(dic, MyEntity.class);
if (isNew) {
// 新增后处理
log.info("用户{}创建了新记录:{}", userProvider.get().getUserId(), entity.getCODE());
// 发送创建通知
sendCreateNotification(entity);
// 更新统计缓存
updateStatisticsCache();
} else {
// 更新后处理
log.info("用户{}更新了记录:{}", userProvider.get().getUserId(), entity.getCODE());
// 发送更新通知
sendUpdateNotification(entity);
}
// 清除相关缓存
clearEntityCache(entity.getID());
// ✅ 正确:如果需要修改数据,先操作entity再转换
if (needsPostProcessing(entity)) {
entity.setLastProcessTime(DateUtil.getNowDate());
// 转换回dic返回
Map<String, Object> result = JsonUtil.entityToMap(entity);
result.putAll(dic); // 保留其他字段
return super.afterSave(result, isNew);
}
return super.afterSave(dic, isNew);
}
常用场景:
- 发送通知消息
- 更新缓存
- 记录操作日志
- 触发后续流程
- 统计数据更新
beforeDelete - 删除前验证
时机:数据删除(软删除)之前
用途:删除权限检查、关联数据验证、业务规则验证
java
@Override
public boolean beforeDelete(Map<String, Object> dic)
throws BusinessException, DataException {
MyEntity entity = JsonUtil.getJsonToBean(dic, MyEntity.class);
// 权限检查
if (!hasDeletePermission(entity)) {
throw new BusinessException("您没有删除此记录的权限");
}
// 状态检查
if ("APPROVED".equals(entity.getSTATUS())) {
throw new BusinessException("已审批的记录不能删除");
}
// 关联数据检查
if (hasRelatedData(entity.getID())) {
throw new BusinessException("存在关联数据,无法删除");
}
// 业务规则检查
if (entity.getAMOUNT() != null && entity.getAMOUNT().compareTo(BigDecimal.ZERO) > 0) {
throw new BusinessException("有金额的记录需要经过审批才能删除");
}
return super.beforeDelete(dic);
}
private boolean hasDeletePermission(MyEntity entity) {
UserInfo user = userProvider.get();
// 创建者或管理员可以删除
return user.getUserId().equals(entity.getCREATORUSER()) || user.isAdmin();
}
private boolean hasRelatedData(String id) {
// 检查是否有子表数据或其他关联数据
return relatedService.countByMainId(id) > 0;
}
常用场景:
- 删除权限验证
- 数据状态检查
- 关联数据验证
- 业务规则验证
afterDelete - 删除后处理
时机:数据成功删除(软删除)之后
用途:清理缓存、发送通知、记录日志
java
@Override
public void afterDelete(Map<String, Object> dic)
throws BusinessException, DataException {
MyEntity entity = JsonUtil.getJsonToBean(dic, MyEntity.class);
// 清理相关缓存
String cacheKey = "business:" + entity.getID();
redisUtil.remove(cacheKey);
// 清理列表缓存
String listCachePattern = "business:list:*";
redisUtil.removePattern(listCachePattern);
// 发送删除通知
String title = "记录删除通知";
String content = "记录\"" + entity.getTITLE() + "\"已被删除";
messageService.sentMessage(getNotificationUsers(), title, content, 1);
// 记录操作日志
log.info("用户{}删除了记录:{}", userProvider.get().getUserId(), entity.getID());
super.afterDelete(dic);
}
子表操作钩子
beforeSaveSubTable - 子表保存前处理
时机:子表数据保存之前
用途:子表数据验证、关联ID设置、业务规则检查
java
@Override
public List<Map<String, Object>> beforeSaveSubTable(Map<String, Object> dic,
Class<?> subTableEntity,
List<Map<String, Object>> subTable)
throws BusinessException {
// 获取主表数据
MyEntity mainEntity = JsonUtil.getJsonToBean(dic, MyEntity.class);
// 验证子表数据完整性
if (subTable.isEmpty()) {
throw new BusinessException("至少需要一条明细记录");
}
BigDecimal totalAmount = BigDecimal.ZERO;
for (Map<String, Object> subItem : subTable) {
// 设置关联ID
subItem.put("MAINID", mainEntity.getID());
// 转换为子表实体进行验证
DetailEntity detail = JsonUtil.getJsonToBean(subItem, DetailEntity.class);
// 验证子表数据
if (StringUtil.isEmpty(detail.getDETAILNAME())) {
throw new BusinessException("明细名称不能为空");
}
if (detail.getQUANTITY() == null || detail.getQUANTITY() <= 0) {
throw new BusinessException("数量必须大于0");
}
if (detail.getAMOUNT() == null || detail.getAMOUNT().compareTo(BigDecimal.ZERO) <= 0) {
throw new BusinessException("金额必须大于0");
}
// 计算总金额
totalAmount = totalAmount.add(detail.getAMOUNT());
// 生成子表ID(如果没有)
if (StringUtil.isEmpty(detail.getID())) {
subItem.put("ID", RandomUtil.uuId());
}
}
// 验证总金额
if (totalAmount.compareTo(new BigDecimal("1000000")) > 0) {
throw new BusinessException("总金额不能超过100万");
}
// 更新主表的总金额
dic.put("TOTALAMOUNT", totalAmount);
return super.beforeSaveSubTable(dic, subTableEntity, subTable);
}
常用场景:
- 设置子表关联ID
- 子表数据验证
- 主子表数据一致性检查
- 汇总计算
afterSaveSubTable - 子表保存后处理
时机:子表数据成功保存之后
用途:更新主表汇总、发送通知、更新缓存
java
@Override
public void afterSaveSubTable(Map<String, Object> dic,
Class<?> subTableEntity,
List<Map<String, Object>> subTable)
throws BusinessException {
MyEntity mainEntity = JsonUtil.getJsonToBean(dic, MyEntity.class);
// 重新计算主表汇总数据
BigDecimal totalAmount = subTable.stream()
.map(item -> JsonUtil.getJsonToBean(item, DetailEntity.class))
.map(DetailEntity::getAMOUNT)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 更新主表
mainEntity.setTOTALAMOUNT(totalAmount);
this.updateById(mainEntity);
// 清理缓存
redisUtil.remove("business:" + mainEntity.getID());
// 记录日志
log.info("主表{}的子表数据已更新,共{}条记录", mainEntity.getID(), subTable.size());
super.afterSaveSubTable(dic, subTableEntity, subTable);
}
工作流钩子
beforeTaskExec - 流程任务执行前
时机:工作流任务执行前(提交、审批、拒绝等操作前)
用途:流程前验证、数据补全、状态检查
java
@Override
public Map<String, Object> beforeTaskExec(Map<String, Object> dic, boolean isNew,
FlowTaskEntity flowTask, FlowModel flowModel,
FlowRecordEnum flowRecordEnum) {
// ✅ 正确:转换为Entity对象进行类型安全操作
MyEntity entity = JsonUtil.getJsonToBean(dic, MyEntity.class);
// 根据流程操作类型进行不同处理
switch (flowRecordEnum) {
case submit:
// 提交时处理
if (StringUtil.isEmpty(entity.getCODE())) {
// 生成业务编号
entity.setCODE(generateBusinessCode());
}
// 验证提交条件
validateForSubmit(entity);
// ✅ 正确:避免硬编码,使用方法获取状态
entity.setSTATUS(getSubmitStatus());
entity.setSUBMITTIME(DateUtil.getNowDate());
break;
case agree:
// 审批通过时处理
log.info("审批人{}同意了申请{}", userProvider.get().getUserId(), entity.getCODE());
entity.setSTATUS(getApprovedStatus());
break;
case reject:
// 拒绝时处理
entity.setSTATUS(getRejectedStatus());
entity.setREJECTTIME(DateUtil.getNowDate());
break;
case revoke:
// 撤回时处理
entity.setSTATUS(getDraftStatus());
entity.setREVOKETIME(DateUtil.getNowDate());
break;
}
// ✅ 正确:最后统一转换回dic
Map<String, Object> result = JsonUtil.entityToMap(entity);
result.putAll(dic); // 保留其他字段
return super.beforeTaskExec(result, isNew, flowTask, flowModel, flowRecordEnum);
}
// ✅ 正确:避免硬编码,提取为私有方法
private String generateBusinessCode() {
String date = DateUtil.dateNow("yyyyMMdd");
String random = RandomUtil.enUuid().substring(0, 4).toUpperCase();
return getCodePrefix() + date + random;
}
private String getCodePrefix() {
return "BIZ"; // 可以从配置或枚举读取
}
private void validateForSubmit(MyEntity entity) {
if (entity.getAMOUNT() == null || entity.getAMOUNT().compareTo(BigDecimal.ZERO) <= 0) {
throw new BusinessException("金额必须大于0才能提交");
}
if (StringUtil.isEmpty(entity.getTITLE())) {
throw new BusinessException("标题不能为空");
}
// 其他提交前验证
}
private String getSubmitStatus() {
return "PENDING"; // 可以从枚举或配置读取
}
private String getApprovedStatus() {
return "APPROVED"; // 可以从枚举或配置读取
}
private String getRejectedStatus() {
return "REJECTED"; // 可以从枚举或配置读取
}
private String getDraftStatus() {
return "DRAFT"; // 可以从枚举或配置读取
}
❌ 错误示例 - 避免这样写:
java
@Override
public Map<String, Object> beforeTaskExec(Map<String, Object> dic, boolean isNew,
FlowTaskEntity flowTask, FlowModel flowModel,
FlowRecordEnum flowRecordEnum) {
MyEntity entity = JsonUtil.getJsonToBean(dic, MyEntity.class);
if (flowRecordEnum == submit) {
// ❌ 错误:同时操作entity和dic(重复操作)
dic.put("CODE", "BIZ20240814001");
dic.put("STATUS", "PENDING");
}
return super.beforeTaskExec(dic, isNew, flowTask, flowModel, flowRecordEnum);
}
afterTaskExec - 流程任务执行后
时机:工作流任务执行后
用途:发送通知、记录日志、更新相关数据
java
@Override
public void afterTaskExec(Map<String, Object> dic, boolean isNew,
FlowTaskEntity flowTask, FlowModel flowModel,
FlowRecordEnum flowRecordEnum)
throws BusinessException, DataException {
MyEntity entity = JsonUtil.getJsonToBean(dic, MyEntity.class);
// 根据操作类型发送不同通知
switch (flowRecordEnum) {
case submit:
// 提交后通知审批人
List<String> approvers = getApprovers(entity);
if (!approvers.isEmpty()) {
String title = "待审批提醒";
String content = String.format("您有新的审批任务:%s", entity.getTITLE());
messageService.sentMessage(approvers, title, content, 1);
}
break;
case agree:
// 审批通过后通知申请人
String approveTitle = "审批通过通知";
String approveContent = String.format("您的申请【%s】已审批通过", entity.getTITLE());
messageService.sentMessage(Arrays.asList(entity.getCREATORUSER()),
approveTitle, approveContent, 1);
break;
case reject:
// 拒绝后通知申请人
String rejectTitle = "审批拒绝通知";
String rejectContent = String.format("您的申请【%s】已被拒绝", entity.getTITLE());
messageService.sentMessage(Arrays.asList(entity.getCREATORUSER()),
rejectTitle, rejectContent, 1);
break;
}
super.afterTaskExec(dic, isNew, flowTask, flowModel, flowRecordEnum);
}
onFlowEnd - 流程结束时
时机:整个工作流程结束时(流程通过)
用途:最终的业务处理、状态更新、资源分配
java
@Override
public void onFlowEnd(Map<String, Object> dic, FlowTaskEntity flowTask,
FlowModel flowModel, FlowRecordEnum flowRecordEnum)
throws BusinessException, DataException {
MyEntity entity = JsonUtil.getJsonToBean(dic, MyEntity.class);
// 注意:此方法只在流程最终通过时调用,无需判断状态
// 更新最终状态
entity.setSTATUS("APPROVED");
entity.setAPPROVALTIME(DateUtil.getNowDate());
this.updateById(entity);
// 执行业务逻辑
executeFinalBusiness(entity);
// 发送最终通知
String title = "流程完成通知";
String content = String.format("您的申请【%s】已完成全部审批流程", entity.getTITLE());
messageService.sentMessage(Arrays.asList(entity.getCREATORUSER()), title, content, 1);
// 通知相关人员
List<String> relatedUsers = getRelatedUsers(entity);
if (!relatedUsers.isEmpty()) {
String relatedTitle = "业务处理通知";
String relatedContent = String.format("申请【%s】已审批完成,请及时处理", entity.getTITLE());
messageService.sentMessage(relatedUsers, relatedTitle, relatedContent, 1);
}
// 记录完成日志
log.info("流程{}已完成,业务ID:{}", flowTask.getFlowId(), entity.getID());
super.onFlowEnd(dic, flowTask, flowModel, flowRecordEnum);
}
flowResurgence - 流程复活
时机:流程被复活时
用途:恢复流程状态、重置数据
java
@Override
public void flowResurgence(Map<String, Object> dic)
throws BusinessException, DataException {
MyEntity entity = JsonUtil.getJsonToBean(dic, MyEntity.class);
// 恢复到流程中状态
entity.setSTATUS("PENDING");
this.updateById(entity);
// 发送复活通知
String title = "流程恢复通知";
String content = String.format("申请【%s】的流程已恢复", entity.getTITLE());
messageService.sentMessage(Arrays.asList(entity.getCREATORUSER()), title, content, 1);
log.info("流程已复活,业务ID:{}", entity.getID());
super.flowResurgence(dic);
}
数据获取钩子
afterGetData - 获取数据后处理
时机:查询单条数据之后
用途:数据转换、敏感信息过滤、附加信息补充
java
@Override
public Map<String, Object> afterGetData(Map<String, Object> dic) {
// ✅ 正确:转换为Entity对象进行类型安全操作
MyEntity entity = JsonUtil.getJsonToBean(dic, MyEntity.class);
// 添加扩展信息 - 只操作entity对象
// 创建人姓名
if (StringUtil.isNotEmpty(entity.getCREATORUSER())) {
String creatorName = userService.getUserName(entity.getCREATORUSER());
entity.setCREATORNAME(creatorName);
}
// 部门名称
if (StringUtil.isNotEmpty(entity.getORGANIZE())) {
String organizeName = organizeService.getOrganizeName(entity.getORGANIZE());
entity.setORGANIZENAME(organizeName);
}
// 状态显示名称
if (StringUtil.isNotEmpty(entity.getSTATUS())) {
String statusName = getStatusDisplayName(entity.getSTATUS());
entity.setSTATUSNAME(statusName);
}
// 格式化时间显示
if (entity.getCREATORTIME() != null) {
String createTimeFormat = DateUtil.dateFormat(entity.getCREATORTIME(), "yyyy-MM-dd HH:mm:ss");
entity.setCREATETIMEFORMAT(createTimeFormat);
}
// 权限信息 - 只操作entity对象
UserInfo user = userProvider.get();
boolean canEdit = canEdit(entity, user);
boolean canDelete = canDelete(entity, user);
entity.setCANEDIT(canEdit);
entity.setCANDELETE(canDelete);
// ✅ 正确:最后统一转换回dic
Map<String, Object> result = JsonUtil.entityToMap(entity);
result.putAll(dic); // 保留原有字段
// 过滤敏感信息(在最终结果上操作)
if (!user.isAdmin()) {
// 非管理员不显示某些敏感字段
result.remove("SENSITIVEINFO");
}
return super.afterGetData(result);
}
❌ 错误示例 - 避免这样写:
java
@Override
public Map<String, Object> afterGetData(Map<String, Object> dic) {
MyEntity entity = JsonUtil.getJsonToBean(dic, MyEntity.class);
// ❌ 错误:同时操作entity和dic
if (StringUtil.isNotEmpty(entity.getSTATUS())) {
String statusName = getStatusDisplayName(entity.getSTATUS());
entity.setSTATUSNAME(statusName); // 操作entity
dic.put("STATUSNAME", statusName); // 又操作dic,重复操作
}
// ❌ 错误:直接在dic上操作,没有经过entity
dic.put("TIMERANGE", "2024-01-01 ~ 2024-01-02");
return super.afterGetData(dic);
}
钩子方法最佳实践
1. 按需实现原则
java
// ✅ 正确:只实现需要的钩子方法
@Slf4j // 必须添加日志注解
@Service
@UseDataSource(DbNameConst.JPWISE_DEMO)
public class BusinessServiceImpl extends BasicDemoServiceImpl<BusinessMapper, BusinessEntity>
implements BusinessService {
// 只有当用户明确需要保存前验证时才添加此方法
@Override
public Map<String, Object> beforeSave(Map<String, Object> dic, Boolean isNew)
throws BusinessException, DataException {
// ✅ 正确:遵循Basic继承指南规范
BusinessEntity entity = JsonUtil.getJsonToBean(dic, BusinessEntity.class);
// 具体的业务验证逻辑
if (isNew) {
entity.setCODE(generateBusinessCode());
entity.setSTATUS(getDefaultStatus());
}
validateBusinessRules(entity);
// 最后统一转换回dic
Map<String, Object> result = JsonUtil.entityToMap(entity);
result.putAll(dic);
return super.beforeSave(result, isNew);
}
}
// ❌ 错误:预先生成所有钩子方法
public class BusinessServiceImpl extends BasicDemoServiceImpl<BusinessMapper, BusinessEntity> {
// 不要预先添加空的钩子方法
@Override
public Map<String, Object> beforeSave(Map<String, Object> dic, Boolean isNew) {
return super.beforeSave(dic, isNew); // 空实现没有意义
}
@Override
public Map<String, Object> afterSave(Map<String, Object> dic, Boolean isNew) {
return super.afterSave(dic, isNew); // 空实现没有意义
}
// ... 其他空钩子方法
}
2. 异常处理规范
java
// ✅ 正确:异常声明与基类一致
@Override
public Map<String, Object> beforeSave(Map<String, Object> dic, Boolean isNew)
throws BusinessException, DataException {
// 使用项目定义的异常类型
if (validationFails) {
throw new BusinessException("业务验证失败");
}
if (dataFormatError) {
throw new DataException("数据格式错误");
}
return super.beforeSave(dic, isNew);
}
// ❌ 错误:异常声明不一致
@Override
public Map<String, Object> beforeSave(Map<String, Object> dic, Boolean isNew)
throws Exception { // 错误:与基类声明不一致
return super.beforeSave(dic, isNew);
}
3. 调用父类方法
java
// ✅ 正确:必须调用父类方法
@Override
public Map<String, Object> beforeSave(Map<String, Object> dic, Boolean isNew)
throws BusinessException, DataException {
// 自定义业务逻辑
customBusinessLogic(dic);
// 必须调用父类方法
return super.beforeSave(dic, isNew);
}
// ❌ 错误:忘记调用父类方法
@Override
public Map<String, Object> beforeSave(Map<String, Object> dic, Boolean isNew) {
customBusinessLogic(dic);
return dic; // 错误:没有调用super方法
}
4. 钩子方法组合使用
多个钩子方法可以组合使用,形成完整的业务流程处理链:
java
@Service
@UseDataSource(DbNameConst.JPWISE_DEMO)
public class BusinessServiceImpl extends BasicDemoServiceImpl<BusinessMapper, BusinessEntity>
implements BusinessService {
// 1. 保存前:数据验证和补全
@Override
public Map<String, Object> beforeSave(Map<String, Object> dic, Boolean isNew) {
BusinessEntity entity = JsonUtil.getJsonToBean(dic, BusinessEntity.class);
if (isNew) {
entity.setCODE(generateBusinessCode());
entity.setSTATUS(getDefaultStatus());
}
validateBusinessRules(entity);
Map<String, Object> result = JsonUtil.entityToMap(entity);
result.putAll(dic);
return super.beforeSave(result, isNew);
}
// 2. 流程提交前:业务验证
@Override
public Map<String, Object> beforeTaskExec(Map<String, Object> dic, boolean isNew,
FlowTaskEntity flowTask, FlowModel flowModel,
FlowRecordEnum flowRecordEnum) {
if (flowRecordEnum == submit) {
BusinessEntity entity = JsonUtil.getJsonToBean(dic, BusinessEntity.class);
validateForSubmit(entity);
entity.setSTATUS("PENDING");
Map<String, Object> result = JsonUtil.entityToMap(entity);
result.putAll(dic);
return super.beforeTaskExec(result, isNew, flowTask, flowModel, flowRecordEnum);
}
return super.beforeTaskExec(dic, isNew, flowTask, flowModel, flowRecordEnum);
}
// 3. 流程结束后:最终处理
@Override
public void onFlowEnd(Map<String, Object> dic, FlowTaskEntity flowTask,
FlowModel flowModel, FlowRecordEnum flowRecordEnum) {
BusinessEntity entity = JsonUtil.getJsonToBean(dic, BusinessEntity.class);
// 发送通知、更新状态、触发后续业务
sendNotification(entity);
updateBusinessStatus(entity);
super.onFlowEnd(dic, flowTask, flowModel, flowRecordEnum);
}
}
📋 核心规范总结
钩子方法标准流程
java
@Override
public Map<String, Object> hookMethodName(Map<String, Object> dic, ...) {
// 1. 转换为Entity对象
MyEntity entity = JsonUtil.getJsonToBean(dic, MyEntity.class);
// 2. 业务逻辑处理
// 只操作entity对象
// 3. 最后转换回dic并返回
Map<String, Object> result = JsonUtil.entityToMap(entity);
result.putAll(dic);
return super.hookMethodName(result, ...);
}
⚠️ 关键要点
- Entity优先 - 转换为Entity对象进行类型安全操作
- 避免双重操作 - 不要同时修改entity和dic
- 按需添加 - 只有明确需要时才添加钩子方法
- 必须调用super - 确保框架逻辑正常执行
💡 详细指南: 完整编码规范请参考 Basic继承指南