news 2026/6/10 10:52:49

Spring Boot整合Activiti的项目中实现抄送功能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot整合Activiti的项目中实现抄送功能

目录

1、实现思路

2、在Spring Boot中集成Activiti

2.1、设计抄送表

2.2、抄送实体类

2.3、实现抄送服务

3、前端集成

3.1、抄送组件

3.2、抄送列表页面

4、高级功能扩展

4.1、邮件通知集成

4.2、消息推送集成(WebSocket)

4.3、 抄送规则配置

4.4、 应用配置文件

4.5、 流程定义中的抄送配置

5、总结


1、实现思路

在Activiti工作流中,抄送功能通常不是直接提供的,但可以通过扩展来实现。抄送功能可以理解为将某个任务的信息发送给相关人员,而不需要他们直接处理任务。在Spring Boot整合Activiti的项目中,我们可以通过以下方式实现抄送功能:

  1. 自定义抄送表:记录抄送的任务、抄送给谁、抄送时间等信息。
  2. 在任务创建或完成时触发抄送逻辑,将任务信息插入抄送表。
  3. 提供接口供用户查看自己被抄送的任务。

在Spring Boot项目中整合Activiti工作流的抄送功能,可以通过以下方案实现:

2、在Spring Boot中集成Activiti

pom.xml中添加Activiti依赖:

<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter</artifactId> <version>7.1.0.M6</version> </dependency>

2.1、设计抄送表

创建抄送表,表结构如下:

CREATE TABLE `act_cc_task` ( `id` varchar(64) NOT NULL COMMENT '主键', `task_id` varchar(64) DEFAULT NULL COMMENT '任务ID', `proc_inst_id` varchar(64) DEFAULT NULL COMMENT '流程实例ID', `proc_def_id` varchar(64) DEFAULT NULL COMMENT '流程定义ID', `title` varchar(255) DEFAULT NULL COMMENT '抄送标题', `content` text COMMENT '抄送内容', `from_user_id` varchar(64) DEFAULT NULL COMMENT '发起人', `to_user_ids` text COMMENT '接收人(多个用逗号分隔)', `status` int(1) DEFAULT '0' COMMENT '状态(0:未读,1:已读)', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `read_time` datetime DEFAULT NULL COMMENT '读取时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2.2、抄送实体类

@Data @TableName("act_cc_task") public class CcTask { @TableId(type = IdType.ASSIGN_ID) private String id; private String taskId; private String procInstId; private String procDefId; private String title; private String content; private String fromUserId; private String toUserIds; // 多个用户用逗号分隔 private Integer status; private Date createTime; private Date readTime; @TableField(exist = false) private List<String> toUserList; // 接收人列表 }

2.3、实现抄送服务

创建一个抄送服务,用于处理抄送逻辑。例如,在任务完成时,将任务抄送给指定人员。

服务接口:

public interface CcTaskService { /** * 创建抄送任务 */ void createCcTask(String taskId, List<String> toUserIds, String title, String content); /** * 获取用户的抄送列表 */ PageInfo<CcTask> getUserCcTasks(String userId, Integer pageNum, Integer pageSize, Integer status); /** * 标记为已读 */ void markAsRead(String ccTaskId, String userId); /** * 批量抄送 */ void batchCcTask(List<String> taskIds, List<String> toUserIds, String reason); }

服务实现:

在任务完成时触发抄送,可以在任务完成事件监听器中触发抄送。例如,创建一个任务监听器

@Service @Slf4j public class CcTaskServiceImpl implements CcTaskService { @Autowired private CcTaskMapper ccTaskMapper; @Autowired private TaskService taskService; @Autowired private RuntimeService runtimeService; @Override @Transactional public void createCcTask(String taskId, List<String> toUserIds, String title, String content) { Task task = taskService.createTaskQuery() .taskId(taskId) .singleResult(); if (task == null) { throw new BusinessException("任务不存在"); } // 获取当前登录用户 String currentUserId = SecurityUtils.getCurrentUserId(); CcTask ccTask = new CcTask(); ccTask.setId(IdUtil.fastSimpleUUID()); ccTask.setTaskId(taskId); ccTask.setProcInstId(task.getProcessInstanceId()); ccTask.setProcDefId(task.getProcessDefinitionId()); ccTask.setTitle(title); ccTask.setContent(content); ccTask.setFromUserId(currentUserId); ccTask.setToUserIds(StringUtils.join(toUserIds, ",")); ccTask.setStatus(0); ccTask.setCreateTime(new Date()); ccTaskMapper.insert(ccTask); // 发送通知(可集成消息推送) sendNotification(ccTask); } /** * 使用监听器自动抄送 */ @Component public static class TaskCcListener implements TaskListener { @Autowired private CcTaskService ccTaskService; @Override public void notify(DelegateTask delegateTask) { String eventName = delegateTask.getEventName(); // 在任务创建时自动抄送 if ("create".equals(eventName)) { Object ccUsers = delegateTask.getVariable("ccUsers"); if (ccUsers != null) { List<String> userIds = (List<String>) ccUsers; if (!CollectionUtils.isEmpty(userIds)) { String taskName = delegateTask.getName(); String content = String.format("任务【%s】需要您知晓", taskName); ccTaskService.createCcTask( delegateTask.getId(), userIds, taskName, content ); } } } } } }

然后在流程定义中,在任务完成事件上绑定这个监听器。可以在BPMN文件中配置,也可以通过代码配置。

控制器层:

@RestController @RequestMapping("/api/cc") @Api(tags = "抄送管理") public class CcTaskController { @Autowired private CcTaskService ccTaskService; @PostMapping("/create") @ApiOperation("创建抄送") public Result createCcTask(@RequestBody CcTaskCreateDTO dto) { ccTaskService.createCcTask( dto.getTaskId(), dto.getToUserIds(), dto.getTitle(), dto.getContent() ); return Result.success(); } @GetMapping("/list") @ApiOperation("获取抄送列表") public Result<PageInfo<CcTask>> getCcList( @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) Integer status) { String userId = SecurityUtils.getCurrentUserId(); PageInfo<CcTask> result = ccTaskService.getUserCcTasks( userId, pageNum, pageSize, status ); return Result.success(result); } @PostMapping("/read/{id}") @ApiOperation("标记已读") public Result markAsRead(@PathVariable String id) { String userId = SecurityUtils.getCurrentUserId(); ccTaskService.markAsRead(id, userId); return Result.success(); } }

3、前端集成

3.1、抄送组件

<template> <div class="cc-task-container"> <!-- 抄送按钮 --> <el-button type="text" @click="showCcDialog"> <i class="el-icon-s-promotion"></i> 抄送 </el-button> <!-- 抄送对话框 --> <el-dialog title="任务抄送" :visible.sync="ccDialogVisible"> <el-form :model="ccForm"> <el-form-item label="接收人"> <el-select v-model="ccForm.userIds" multiple filterable placeholder="请选择接收人"> <el-option v-for="user in userList" :key="user.id" :label="user.name" :value="user.id"> </el-option> </el-select> </el-form-item> <el-form-item label="抄送说明"> <el-input type="textarea" v-model="ccForm.content" placeholder="请输入抄送说明" rows="4"> </el-input> </el-form-item> </el-form> <div slot="footer"> <el-button @click="ccDialogVisible = false">取消</el-button> <el-button type="primary" @click="submitCc">确定</el-button> </div> </el-dialog> </div> </template> <script> export default { props: { taskId: String, taskName: String }, data() { return { ccDialogVisible: false, userList: [], ccForm: { userIds: [], content: '' } } }, methods: { showCcDialog() { this.ccDialogVisible = true this.loadUserList() }, async loadUserList() { const res = await this.$api.user.getUserList() this.userList = res.data }, async submitCc() { const params = { taskId: this.taskId, toUserIds: this.ccForm.userIds, title: `任务【${this.taskName}】抄送`, content: this.ccForm.content } await this.$api.cc.create(params) this.$message.success('抄送成功') this.ccDialogVisible = false this.$emit('cc-success') } } } </script>

3.2、抄送列表页面

<template> <div class="cc-task-list"> <el-tabs v-model="activeStatus" @tab-click="handleTabClick"> <el-tab-pane label="未读" name="0"></el-tab-pane> <el-tab-pane label="已读" name="1"></el-tab-pane> <el-tab-pane label="全部" name=""></el-tab-pane> </el-tabs> <el-table :data="ccList" v-loading="loading"> <el-table-column prop="title" label="标题" width="200"> <template slot-scope="{row}"> <span :class="{'unread': row.status === 0}"> {{ row.title }} </span> </template> </el-table-column> <el-table-column prop="content" label="内容"></el-table-column> <el-table-column prop="fromUserName" label="发起人" width="100"> </el-table-column> <el-table-column prop="createTime" label="时间" width="180"> <template slot-scope="{row}"> {{ formatDate(row.createTime) }} </template> </el-table-column> <el-table-column label="操作" width="120"> <template slot-scope="{row}"> <el-button v-if="row.status === 0" type="text" @click="markAsRead(row.id)"> 标记已读 </el-button> <el-button type="text" @click="viewProcess(row.procInstId)"> 查看流程 </el-button> </template> </el-table-column> </el-table> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pagination.pageNum" :page-sizes="[10, 20, 50, 100]" :page-size="pagination.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="pagination.total"> </el-pagination> </div> </template>

前端可以调用上述接口展示抄送列表,并允许用户标记已读。

注意事项

  • 抄送功能可以根据实际需求进行扩展,例如增加抄送类型(任务创建时抄送、任务完成时抄送等)。

  • 抄送人员可以从任务变量、流程变量、固定配置或者从用户选择中获取。

  • 抄送任务可能不需要处理,但需要记录,因此抄送表的设计可以根据业务需求调整。

4、高级功能扩展

4.1、邮件通知集成

@Component public class EmailCcNotifier { @Autowired private JavaMailSender mailSender; @Value("${spring.mail.username}") private String from; public void sendCcNotification(CcTask ccTask, User user) { SimpleMailMessage message = new SimpleMailMessage(); message.setFrom(from); message.setTo(user.getEmail()); message.setSubject("工作流抄送通知:" + ccTask.getTitle()); message.setText(buildEmailContent(ccTask)); mailSender.send(message); } private String buildEmailContent(CcTask ccTask) { return String.format( "您收到一条工作流抄送:\n" + "标题:%s\n" + "内容:%s\n" + "发起人:%s\n" + "时间:%s\n" + "请登录系统查看详情。", ccTask.getTitle(), ccTask.getContent(), ccTask.getFromUserId(), DateUtil.formatDateTime(ccTask.getCreateTime()) ); } }

4.2、消息推送集成(WebSocket)

@ServerEndpoint("/websocket/cc") @Component public class CcWebSocket { private static Map<String, Session> sessions = new ConcurrentHashMap<>(); @OnOpen public void onOpen(Session session) { String userId = getUserIdFromSession(session); sessions.put(userId, session); } /** * 向指定用户推送抄送消息 */ public static void sendCcMessage(String userId, CcTask ccTask) { Session session = sessions.get(userId); if (session != null && session.isOpen()) { try { String message = JSON.toJSONString( Map.of("type", "cc", "data", ccTask) ); session.getBasicRemote().sendText(message); } catch (IOException e) { log.error("发送WebSocket消息失败", e); } } } }

4.3、 抄送规则配置

@Component public class CcRuleEngine { /** * 根据规则自动抄送 * 规则示例: * 1. 特定节点自动抄送 * 2. 金额大于阈值抄送 * 3. 特定部门任务抄送 */ public List<String> getCcUsersByRule( String processDefinitionId, String taskDefinitionKey, Map<String, Object> variables) { List<String> userIds = new ArrayList<>(); // 示例:根据任务节点配置抄送 if ("approve".equals(taskDefinitionKey)) { // 审批节点抄送给部门经理 String deptId = (String) variables.get("deptId"); userIds.addAll(getDeptManagers(deptId)); } // 示例:根据金额阈值抄送 Double amount = (Double) variables.get("amount"); if (amount != null && amount > 10000) { userIds.addAll(getFinanceUsers()); } return userIds.stream().distinct().collect(Collectors.toList()); } }

4.4、 应用配置文件

# application.yml activiti: cc: enabled: true # 是否启用邮件通知 email-notify: true # 是否启用站内信 message-notify: true # 默认抄送人(角色) default-cc-roles: ROLE_DEPT_MANAGER,ROLE_ADMIN

4.5、 流程定义中的抄送配置

<!-- 在BPMN文件中添加抄送配置 --> <userTask id="approveTask" name="审批任务"> <extensionElements> <activiti:taskListener event="create" class="com.xxx.listener.AutoCcTaskListener"/> <activiti:formProperty id="ccUsers" name="抄送人" type="users"/> </extensionElements> </userTask>

5、总结

抄送功能的实现要点:

  1. 数据持久化:设计抄送表记录抄送信息

  2. 业务逻辑:提供抄送CRUD服务

  3. 流程集成:通过监听器自动触发抄送

  4. 用户通知:集成多种通知方式(站内信、邮件、推送)

  5. 权限控制:确保用户只能操作自己的抄送记录

  6. 配置灵活:支持规则引擎和动态配置

这种实现方式既保持了工作流引擎的纯净性,又通过扩展实现了业务需要的抄送功能。


“人的一生会经历很多痛苦,但回头想想,都是传奇”。



版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 17:21:28

ET框架冷启动性能工程:从架构视角重构客户端启动体验

ET框架冷启动性能工程&#xff1a;从架构视角重构客户端启动体验 【免费下载链接】ET Unity3D 客户端和 C# 服务器框架。 项目地址: https://gitcode.com/GitHub_Trending/et/ET 问题诊断与价值定位 在游戏开发领域&#xff0c;客户端冷启动时间已成为衡量技术架构成熟…

作者头像 李华
网站建设 2026/6/10 17:19:14

终极解决方案:一键实现飞书文档到Markdown的高效转换

终极解决方案&#xff1a;一键实现飞书文档到Markdown的高效转换 【免费下载链接】cloud-document-converter Convert Lark Doc to Markdown 项目地址: https://gitcode.com/gh_mirrors/cl/cloud-document-converter 还在为飞书文档格式转换而烦恼吗&#xff1f;cloud-d…

作者头像 李华
网站建设 2026/6/9 21:08:50

AMD Ryzen处理器性能调优完全指南:5分钟掌握RyzenAdj核心用法

AMD Ryzen处理器性能调优完全指南&#xff1a;5分钟掌握RyzenAdj核心用法 【免费下载链接】RyzenAdj Adjust power management settings for Ryzen APUs 项目地址: https://gitcode.com/gh_mirrors/ry/RyzenAdj 想要让您的AMD Ryzen笔记本电脑发挥出真正的实力吗&#x…

作者头像 李华
网站建设 2026/6/10 17:25:11

那些漏洞挖掘高手都是怎么挖漏洞的?

前言 说到安全就不能不说漏洞&#xff0c;而说到漏洞就不可避免地会说到三座大山&#xff1a; 漏洞分析 漏洞利用 漏洞挖掘 从个人的感觉上来看&#xff0c;这三者尽管通常水乳交融、相互依赖&#xff0c;但难度是不尽相同的。本文就这三者分别谈谈自己的经验和想法。 漏洞分析…

作者头像 李华
网站建设 2026/6/10 17:19:21

玩转AI视频生成:Wan2.1-I2V模型从入门到精通

想要将静态图片变成生动的短视频吗&#xff1f;Wan2.1-I2V-14B-480P-StepDistill-CfgDistill-Lightx2v模型正是您需要的利器&#xff01;这款基于LightX2V框架的AI模型能够快速将图像转换为视频内容&#xff0c;支持FP8和INT8量化技术&#xff0c;让您在普通电脑上也能享受专业…

作者头像 李华
网站建设 2026/6/10 17:31:20

270M参数撬动百亿市场:Gemma 3微型模型重塑边缘AI格局

270M参数撬动百亿市场&#xff1a;Gemma 3微型模型重塑边缘AI格局 【免费下载链接】gemma-3-270m-it-unsloth-bnb-4bit 项目地址: https://ai.gitcode.com/hf_mirrors/unsloth/gemma-3-270m-it-unsloth-bnb-4bit 导语 手机25次对话仅耗电0.75%&#xff0c;谷歌Gemma 3…

作者头像 李华