feat(bpm): 添加流程映射配置功能
- 新增流程映射配置表和相关 SQL - 实现流程映射配置的 CRUD 接口和服务 - 添加流程数据动态查询功能 - 采用二级缓存架构(内存 + Redis)提高查询性能
This commit is contained in:
parent
64baec0471
commit
e09b8c6b9d
26
sql/mysql/bmp_process_mapping_config.sql
Normal file
26
sql/mysql/bmp_process_mapping_config.sql
Normal file
@ -0,0 +1,26 @@
|
||||
-- 流程映射配置表
|
||||
CREATE TABLE `bpm_process_mapping_config` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`process_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程唯一标识(如:ORDER,PAYMENT)',
|
||||
`process_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程显示名称',
|
||||
`table_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '物理表名(如:order_info)',
|
||||
`entity_class` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '实体类全限定名(如:com.example.order.OrderDO)',
|
||||
`mapper_class` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Mapper接口全限定名(如:com.example.order.OrderMapper)',
|
||||
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '流程描述',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_process_code` (`process_code`, `deleted`) COMMENT '流程代码唯一索引',
|
||||
KEY `idx_tenant_id` (`tenant_id`) COMMENT '租户ID索引'
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='流程映射配置表';
|
||||
|
||||
-- 插入示例数据
|
||||
INSERT INTO `bpm_process_mapping_config`
|
||||
(`process_code`, `process_name`, `table_name`, `entity_class`, `mapper_class`, `description`, `creator`, `tenant_id`)
|
||||
VALUES
|
||||
('LEAVE', '请假流程', 'bpm_oa_leave', 'cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO', 'cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOALeaveMapper', '员工请假申请流程配置', 'system', 0),
|
||||
('REIMBURSEMENT', '报销流程', 'bpm_oa_reimbursement', 'cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReimbursementDO', 'cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAReimbursementMapper', '员工报销申请流程配置', 'system', 0);
|
@ -129,4 +129,8 @@ public interface ErrorCodeConstants {
|
||||
|
||||
|
||||
ErrorCode BPM_SYSTEM_BUG = new ErrorCode(1_009_012_001, "系统问题,请联系管理员");
|
||||
|
||||
// ========== 流程映射配置模块 1-009-014-000 ==========
|
||||
ErrorCode PROCESS_MAPPING_CONFIG_NOT_EXISTS = new ErrorCode(1_009_014_001, "流程映射配置不存在");
|
||||
ErrorCode PROCESS_MAPPING_CONFIG_CODE_DUPLICATE = new ErrorCode(1_009_014_002, "流程代码已存在,不允许重复");
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.processmapping;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo.BpmProcessMappingConfigCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo.BpmProcessMappingConfigPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo.BpmProcessMappingConfigRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo.BpmProcessMappingConfigUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.processmapping.BpmProcessMappingConfigDO;
|
||||
import cn.iocoder.yudao.module.bpm.service.processmapping.ProcessMappingConfigService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
/**
|
||||
* 管理后台 - 流程映射配置
|
||||
*
|
||||
* @author 系统
|
||||
*/
|
||||
@Tag(name = "管理后台 - 流程映射配置")
|
||||
@RestController
|
||||
@RequestMapping("/bpm/process-mapping-config")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class BpmProcessMappingConfigController {
|
||||
|
||||
@Resource
|
||||
private ProcessMappingConfigService processMappingConfigService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建流程映射配置")
|
||||
@PreAuthorize("@ss.hasPermission('bpm:process-mapping-config:create')")
|
||||
public CommonResult<Long> createProcessMappingConfig(@Valid @RequestBody BpmProcessMappingConfigCreateReqVO createReqVO) {
|
||||
return success(processMappingConfigService.createProcessMappingConfig(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新流程映射配置")
|
||||
@PreAuthorize("@ss.hasPermission('bmp:process-mapping-config:update')")
|
||||
public CommonResult<Boolean> updateProcessMappingConfig(@Valid @RequestBody BpmProcessMappingConfigUpdateReqVO updateReqVO) {
|
||||
processMappingConfigService.updateProcessMappingConfig(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除流程映射配置")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('bpm:process-mapping-config:delete')")
|
||||
public CommonResult<Boolean> deleteProcessMappingConfig(@RequestParam("id") Long id) {
|
||||
processMappingConfigService.deleteProcessMappingConfig(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得流程映射配置")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('bpm:process-mapping-config:query')")
|
||||
public CommonResult<BpmProcessMappingConfigRespVO> getProcessMappingConfig(@RequestParam("id") Long id) {
|
||||
BpmProcessMappingConfigDO config = processMappingConfigService.getProcessMappingConfig(id);
|
||||
return success(BeanUtils.toBean(config, BpmProcessMappingConfigRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得流程映射配置分页")
|
||||
@PreAuthorize("@ss.hasPermission('bpm:process-mapping-config:query')")
|
||||
public CommonResult<PageResult<BpmProcessMappingConfigRespVO>> getProcessMappingConfigPage(@Valid BpmProcessMappingConfigPageReqVO pageReqVO) {
|
||||
PageResult<BpmProcessMappingConfigDO> pageResult = processMappingConfigService.getProcessMappingConfigPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, BpmProcessMappingConfigRespVO.class));
|
||||
}
|
||||
|
||||
@PostMapping("/refresh-cache")
|
||||
@Operation(summary = "刷新流程映射配置缓存")
|
||||
@PreAuthorize("@ss.hasPermission('bpm:process-mapping-config:update')")
|
||||
public CommonResult<Boolean> refreshCache() {
|
||||
processMappingConfigService.refreshCache();
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.processmapping;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.bpm.service.processmapping.ProcessQueryService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.Serializable;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
/**
|
||||
* 管理后台 - 流程数据查询
|
||||
*
|
||||
* @author 系统
|
||||
*/
|
||||
@Tag(name = "管理后台 - 流程数据查询")
|
||||
@RestController
|
||||
@RequestMapping("/bpm/process-query")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class BpmProcessQueryController {
|
||||
|
||||
@Resource
|
||||
private ProcessQueryService processQueryService;
|
||||
|
||||
@GetMapping("/data")
|
||||
@Operation(summary = "根据流程代码和ID查询数据")
|
||||
@Parameter(name = "processCode", description = "流程代码", required = true, example = "ORDER")
|
||||
@Parameter(name = "id", description = "数据ID", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('bpm:process-query:data')")
|
||||
public CommonResult<Object> getProcessData(@RequestParam("processCode") String processCode,
|
||||
@RequestParam("id") Serializable id) {
|
||||
Object result = processQueryService.queryById(processCode, id);
|
||||
return success(result);
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* 流程映射配置创建 Request VO
|
||||
*
|
||||
* @author 系统
|
||||
*/
|
||||
@Schema(description = "管理后台 - 流程映射配置创建 Request VO")
|
||||
@Data
|
||||
public class BpmProcessMappingConfigCreateReqVO {
|
||||
|
||||
@Schema(description = "流程唯一标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "ORDER")
|
||||
@NotBlank(message = "流程代码不能为空")
|
||||
@Size(max = 64, message = "流程代码长度不能超过64个字符")
|
||||
private String processCode;
|
||||
|
||||
@Schema(description = "流程显示名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单流程")
|
||||
@NotBlank(message = "流程名称不能为空")
|
||||
@Size(max = 128, message = "流程名称长度不能超过128个字符")
|
||||
private String processName;
|
||||
|
||||
@Schema(description = "物理表名", requiredMode = Schema.RequiredMode.REQUIRED, example = "order_info")
|
||||
@NotBlank(message = "表名不能为空")
|
||||
@Size(max = 64, message = "表名长度不能超过64个字符")
|
||||
private String tableName;
|
||||
|
||||
@Schema(description = "实体类全限定名", requiredMode = Schema.RequiredMode.REQUIRED, example = "com.example.order.OrderDO")
|
||||
@NotBlank(message = "实体类不能为空")
|
||||
@Size(max = 255, message = "实体类长度不能超过255个字符")
|
||||
private String entityClass;
|
||||
|
||||
@Schema(description = "Mapper接口全限定名", requiredMode = Schema.RequiredMode.REQUIRED, example = "com.example.order.OrderMapper")
|
||||
@NotBlank(message = "Mapper类不能为空")
|
||||
@Size(max = 255, message = "Mapper类长度不能超过255个字符")
|
||||
private String mapperClass;
|
||||
|
||||
@Schema(description = "流程描述", example = "订单相关的业务流程")
|
||||
@Size(max = 255, message = "描述长度不能超过255个字符")
|
||||
private String description;
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
/**
|
||||
* 流程映射配置分页 Request VO
|
||||
*
|
||||
* @author 系统
|
||||
*/
|
||||
@Schema(description = "管理后台 - 流程映射配置分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class BpmProcessMappingConfigPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "流程代码", example = "ORDER")
|
||||
private String processCode;
|
||||
|
||||
@Schema(description = "流程名称", example = "订单流程")
|
||||
private String processName;
|
||||
|
||||
@Schema(description = "表名", example = "order_info")
|
||||
private String tableName;
|
||||
|
||||
@Schema(description = "实体类", example = "com.example.order.OrderDO")
|
||||
private String entityClass;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 流程映射配置 Response VO
|
||||
*
|
||||
* @author 系统
|
||||
*/
|
||||
@Schema(description = "管理后台 - 流程映射配置 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class BpmProcessMappingConfigRespVO extends BpmProcessMappingConfigCreateReqVO {
|
||||
|
||||
@Schema(description = "配置ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 流程映射配置更新 Request VO
|
||||
*
|
||||
* @author 系统
|
||||
*/
|
||||
@Schema(description = "管理后台 - 流程映射配置更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class BpmProcessMappingConfigUpdateReqVO extends BpmProcessMappingConfigCreateReqVO {
|
||||
|
||||
@Schema(description = "配置ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "配置ID不能为空")
|
||||
private Long id;
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程数据查询 Request VO
|
||||
*
|
||||
* @author 系统
|
||||
*/
|
||||
@Schema(description = "管理后台 - 流程数据查询 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class ProcessDataQueryReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "流程代码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ORDER")
|
||||
@NotBlank(message = "流程代码不能为空")
|
||||
private String processCode;
|
||||
|
||||
@Schema(description = "数据ID", example = "1024")
|
||||
private Serializable id;
|
||||
|
||||
@Schema(description = "查询条件", example = "{\"status\": 1, \"name\": \"测试\"}")
|
||||
private Map<String, Object> queryParams;
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package cn.iocoder.yudao.module.bpm.dal.mysql.processmapping;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo.BpmProcessMappingConfigPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.processmapping.BpmProcessMappingConfigDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 流程映射配置 Mapper
|
||||
*
|
||||
* @author 系统
|
||||
*/
|
||||
@Mapper
|
||||
public interface BpmProcessMappingConfigMapper extends BaseMapperX<BpmProcessMappingConfigDO> {
|
||||
|
||||
default PageResult<BpmProcessMappingConfigDO> selectPage(BpmProcessMappingConfigPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<BpmProcessMappingConfigDO>()
|
||||
.likeIfPresent(BpmProcessMappingConfigDO::getProcessCode, reqVO.getProcessCode())
|
||||
.likeIfPresent(BpmProcessMappingConfigDO::getProcessName, reqVO.getProcessName())
|
||||
.likeIfPresent(BpmProcessMappingConfigDO::getTableName, reqVO.getTableName())
|
||||
.likeIfPresent(BpmProcessMappingConfigDO::getEntityClass, reqVO.getEntityClass())
|
||||
.betweenIfPresent(BpmProcessMappingConfigDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(BpmProcessMappingConfigDO::getId));
|
||||
}
|
||||
|
||||
default BpmProcessMappingConfigDO selectByProcessCode(String processCode) {
|
||||
return selectOne(BpmProcessMappingConfigDO::getProcessCode, processCode);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.processmapping;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo.BpmProcessMappingConfigCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo.BpmProcessMappingConfigPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo.BpmProcessMappingConfigUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.processmapping.BpmProcessMappingConfigDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 流程映射配置 Service 接口
|
||||
*
|
||||
* @author 系统
|
||||
*/
|
||||
public interface ProcessMappingConfigService {
|
||||
|
||||
/**
|
||||
* 创建流程映射配置
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createProcessMappingConfig(@Valid BpmProcessMappingConfigCreateReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新流程映射配置
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateProcessMappingConfig(@Valid BpmProcessMappingConfigUpdateReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除流程映射配置
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteProcessMappingConfig(Long id);
|
||||
|
||||
/**
|
||||
* 获得流程映射配置
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 流程映射配置
|
||||
*/
|
||||
BpmProcessMappingConfigDO getProcessMappingConfig(Long id);
|
||||
|
||||
/**
|
||||
* 根据流程代码获取配置
|
||||
*
|
||||
* @param processCode 流程代码
|
||||
* @return 流程映射配置
|
||||
*/
|
||||
BpmProcessMappingConfigDO getProcessMappingConfigByCode(String processCode);
|
||||
|
||||
/**
|
||||
* 获得流程映射配置分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 流程映射配置分页
|
||||
*/
|
||||
PageResult<BpmProcessMappingConfigDO> getProcessMappingConfigPage(BpmProcessMappingConfigPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 刷新缓存
|
||||
*/
|
||||
void refreshCache();
|
||||
|
||||
}
|
@ -0,0 +1,200 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.processmapping;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.cache.CacheUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo.BpmProcessMappingConfigCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo.BpmProcessMappingConfigPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.processmapping.vo.BpmProcessMappingConfigUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.processmapping.BpmProcessMappingConfigDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.processmapping.BpmProcessMappingConfigMapper;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.Duration;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_MAPPING_CONFIG_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* 流程映射配置 Service 实现类
|
||||
*
|
||||
* 使用二级缓存架构:
|
||||
* 1. 一级缓存(内存):Google Guava LoadingCache,10分钟过期
|
||||
* 2. 二级缓存(Redis):Spring Cache,1小时过期
|
||||
* 3. 数据库:MySQL
|
||||
*
|
||||
* @author 系统
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class ProcessMappingConfigServiceImpl implements ProcessMappingConfigService {
|
||||
|
||||
private static final String CACHE_KEY_PREFIX = "process_mapping_config";
|
||||
|
||||
@Resource
|
||||
private BpmProcessMappingConfigMapper processMappingConfigMapper;
|
||||
|
||||
/**
|
||||
* 一级缓存(内存)- Google Guava LoadingCache
|
||||
* 缓存key为processCode,缓存时间10分钟
|
||||
*/
|
||||
@Getter
|
||||
private final LoadingCache<String, BpmProcessMappingConfigDO> localCache = CacheUtils.buildAsyncReloadingCache(
|
||||
Duration.ofMinutes(10L),
|
||||
new CacheLoader<String, BpmProcessMappingConfigDO>() {
|
||||
@Override
|
||||
public BpmProcessMappingConfigDO load(String processCode) {
|
||||
log.info("[load][一级缓存miss,从二级缓存加载] processCode={}", processCode);
|
||||
// 从二级缓存(Redis)加载
|
||||
BpmProcessMappingConfigDO config = getFromRedisCache(processCode);
|
||||
return config != null ? config : new BpmProcessMappingConfigDO(); // 避免缓存穿透
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createProcessMappingConfig(BpmProcessMappingConfigCreateReqVO createReqVO) {
|
||||
// 校验processCode唯一性
|
||||
validateProcessCodeUnique(null, createReqVO.getProcessCode());
|
||||
|
||||
// 插入
|
||||
BpmProcessMappingConfigDO config = BeanUtil.toBean(createReqVO, BpmProcessMappingConfigDO.class);
|
||||
processMappingConfigMapper.insert(config);
|
||||
|
||||
// 清除缓存
|
||||
evictCache(createReqVO.getProcessCode());
|
||||
|
||||
return config.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateProcessMappingConfig(BpmProcessMappingConfigUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
BpmProcessMappingConfigDO oldConfig = validateProcessMappingConfigExists(updateReqVO.getId());
|
||||
|
||||
// 校验processCode唯一性
|
||||
if (!oldConfig.getProcessCode().equals(updateReqVO.getProcessCode())) {
|
||||
validateProcessCodeUnique(updateReqVO.getId(), updateReqVO.getProcessCode());
|
||||
}
|
||||
|
||||
// 更新
|
||||
BpmProcessMappingConfigDO updateObj = BeanUtil.toBean(updateReqVO, BpmProcessMappingConfigDO.class);
|
||||
processMappingConfigMapper.updateById(updateObj);
|
||||
|
||||
// 清除缓存
|
||||
evictCache(oldConfig.getProcessCode());
|
||||
if (!oldConfig.getProcessCode().equals(updateReqVO.getProcessCode())) {
|
||||
evictCache(updateReqVO.getProcessCode());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteProcessMappingConfig(Long id) {
|
||||
// 校验存在
|
||||
BpmProcessMappingConfigDO config = validateProcessMappingConfigExists(id);
|
||||
|
||||
// 删除
|
||||
processMappingConfigMapper.deleteById(id);
|
||||
|
||||
// 清除缓存
|
||||
evictCache(config.getProcessCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BpmProcessMappingConfigDO getProcessMappingConfig(Long id) {
|
||||
return processMappingConfigMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BpmProcessMappingConfigDO getProcessMappingConfigByCode(String processCode) {
|
||||
try {
|
||||
// 先从一级缓存(内存)获取
|
||||
BpmProcessMappingConfigDO config = localCache.get(processCode);
|
||||
if (config != null && config.getId() != null) {
|
||||
log.debug("[getProcessMappingConfigByCode][一级缓存命中] processCode={}", processCode);
|
||||
return config;
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
log.error("[getProcessMappingConfigByCode][缓存异常] processCode={}", processCode, e);
|
||||
// 缓存异常时直接查询数据库
|
||||
return processMappingConfigMapper.selectByProcessCode(processCode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从二级缓存(Redis)获取配置
|
||||
* 使用Spring Cache注解,自动管理Redis缓存
|
||||
*/
|
||||
@Cacheable(value = CACHE_KEY_PREFIX + "#1h", key = "#processCode", unless = "#result == null")
|
||||
public BpmProcessMappingConfigDO getFromRedisCache(String processCode) {
|
||||
log.info("[getFromRedisCache][二级缓存miss,从数据库加载] processCode={}", processCode);
|
||||
// 从数据库查询
|
||||
return processMappingConfigMapper.selectByProcessCode(processCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<BpmProcessMappingConfigDO> getProcessMappingConfigPage(BpmProcessMappingConfigPageReqVO pageReqVO) {
|
||||
return processMappingConfigMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshCache() {
|
||||
// 清空一级缓存
|
||||
localCache.invalidateAll();
|
||||
log.info("[refreshCache][已清空一级缓存]");
|
||||
|
||||
// 清空二级缓存(通过Spring Cache管理)
|
||||
// 注意:这里需要具体实现清空所有Redis缓存的逻辑
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除指定processCode的缓存
|
||||
*/
|
||||
@CacheEvict(value = CACHE_KEY_PREFIX + "#1h", key = "#processCode")
|
||||
public void evictCache(String processCode) {
|
||||
// 清除一级缓存
|
||||
localCache.invalidate(processCode);
|
||||
log.info("[evictCache][已清除缓存] processCode={}", processCode);
|
||||
// 清除二级缓存由@CacheEvict注解自动处理
|
||||
}
|
||||
|
||||
private void validateProcessCodeUnique(Long id, String processCode) {
|
||||
BpmProcessMappingConfigDO config = processMappingConfigMapper.selectByProcessCode(processCode);
|
||||
if (config == null) {
|
||||
return;
|
||||
}
|
||||
// 如果 id 为空,说明不用比较是否为相同 id 的配置
|
||||
if (id == null) {
|
||||
throw exception(PROCESS_MAPPING_CONFIG_NOT_EXISTS);
|
||||
}
|
||||
if (!config.getId().equals(id)) {
|
||||
throw exception(PROCESS_MAPPING_CONFIG_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
private BpmProcessMappingConfigDO validateProcessMappingConfigExists(Long id) {
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
BpmProcessMappingConfigDO config = processMappingConfigMapper.selectById(id);
|
||||
if (config == null) {
|
||||
throw exception(PROCESS_MAPPING_CONFIG_NOT_EXISTS);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.processmapping;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 流程动态查询 Service 接口
|
||||
*
|
||||
* @author 系统
|
||||
*/
|
||||
public interface ProcessQueryService {
|
||||
|
||||
/**
|
||||
* 根据流程代码和ID查询数据
|
||||
*
|
||||
* @param processCode 流程标识(如"ORDER")
|
||||
* @param id 数据主键
|
||||
* @return 对应的实体对象
|
||||
*/
|
||||
Object queryById(String processCode, Serializable id);
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.processmapping;
|
||||
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.processmapping.BpmProcessMappingConfigDO;
|
||||
import cn.iocoder.yudao.module.bpm.framework.core.util.ReflectionInvoker;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.Serializable;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_MAPPING_CONFIG_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* 流程动态查询 Service 实现类
|
||||
*
|
||||
* @author 系统
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class ProcessQueryServiceImpl implements ProcessQueryService {
|
||||
|
||||
@Resource
|
||||
private ProcessMappingConfigService processMappingConfigService;
|
||||
|
||||
@Override
|
||||
public Object queryById(String processCode, Serializable id) {
|
||||
// 1. 获取流程配置
|
||||
BpmProcessMappingConfigDO config = getProcessMappingConfig(processCode);
|
||||
|
||||
// 2. 动态获取Mapper实例
|
||||
Object mapperBean = getMapperBean(config.getMapperClass());
|
||||
|
||||
// 3. 调用selectById方法
|
||||
return ReflectionInvoker.invokeMapperMethod(mapperBean, "selectById", Serializable.class, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流程映射配置
|
||||
*/
|
||||
private BpmProcessMappingConfigDO getProcessMappingConfig(String processCode) {
|
||||
BpmProcessMappingConfigDO config = processMappingConfigService.getProcessMappingConfigByCode(processCode);
|
||||
if (config == null) {
|
||||
throw exception(PROCESS_MAPPING_CONFIG_NOT_EXISTS);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态获取Mapper Bean实例
|
||||
*/
|
||||
private Object getMapperBean(String mapperClassName) {
|
||||
try {
|
||||
Class<?> mapperClass = ClassUtil.loadClass(mapperClassName);
|
||||
return SpringUtil.getBean(mapperClass);
|
||||
} catch (Exception e) {
|
||||
log.error("[getMapperBean][获取Mapper实例失败] mapperClassName={}", mapperClassName, e);
|
||||
throw new ServiceException(500, String.format("获取Mapper实例失败: %s", e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user