news 2026/2/25 4:53:01

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/2/26 3:22:33

WINCC实现手机 APP 远程监控及短信报警方案

在工业自动化领域&#xff0c;实时监控与及时响应异常情况是保障生产稳定运行的关键。本文将详细介绍如何结合 WINCC、巨控 OPC560 产品实现手机 APP 远程监控与短信报警功能&#xff0c;为工业生产管理提供高效便捷的解决方案。一、实现原理1. 系统架构组成WINCC实现手机 APP …

作者头像 李华
网站建设 2026/2/24 17:35:53

《Python学习手册》第1章 Python概述

一、课程介绍 1.1 电子书介绍 如果你正在公众号或者CSDN翻阅这本书,想弄清它到底讲什么,可以先记住一句话: Python 是当今使用最广泛的编程语言之一,几乎渗透到所有计算机应用领域;它语法简洁、容易上手,是零基础入门编程的理想选择。 CSDN地址:https://blog.csdn.ne…

作者头像 李华
网站建设 2026/2/25 9:25:54

Obsidian图像工具包:终极图片管理与编辑指南

Obsidian图像工具包&#xff1a;终极图片管理与编辑指南 【免费下载链接】obsidian-image-toolkit An Obsidian plugin for viewing an image. 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-image-toolkit Obsidian图像工具包是专为Obsidian笔记用户设计的强大…

作者头像 李华
网站建设 2026/2/23 14:05:27

自主高性价比、高精度车规级姿态感知、倾角感知模组-应用消费级无人机、自动驾驶、机器人、智能制造、基础设施、智能穿戴等

自主高性价比、高精度车规级姿态感知、倾角感知模组-应用消费级无人机、自动驾驶、机器人、智能制造、基础设施、智能穿戴等在小说阅读器中沉浸阅读IMU 惯性测量单元(Inertial Measurement Unit) 是测量物体三轴角速度和加速度的设备。一个IMU内可能会装有三轴陀螺仪和三轴加速…

作者头像 李华
网站建设 2026/2/23 10:22:50

ComfyUI智能修复技术:图像处理的革命性突破

ComfyUI智能修复技术&#xff1a;图像处理的革命性突破 【免费下载链接】ComfyUI-Inpaint-CropAndStitch ComfyUI nodes to crop before sampling and stitch back after sampling that speed up inpainting 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-Inpaint-Cr…

作者头像 李华