news 2026/5/26 17:43:06

SpringBoot + Activiti6.0实战:手把手教你搞定请假审批系统(附完整源码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot + Activiti6.0实战:手把手教你搞定请假审批系统(附完整源码)

SpringBoot与Activiti6.0深度整合:构建企业级请假审批系统实战指南

在当今企业数字化转型浪潮中,业务流程自动化已成为提升运营效率的关键。本文将带您深入探索如何利用SpringBoot与Activiti6.0构建一个功能完备的请假审批系统,从环境搭建到生产部署,全程采用工程化实践方案。

1. 环境准备与基础配置

1.1 技术栈选型与依赖管理

现代Java企业应用开发中,SpringBoot已成为事实上的标准框架,而Activiti作为成熟的BPMN2.0流程引擎,二者的结合能够快速实现复杂业务流程的数字化。以下是核心依赖配置:

<dependencies> <!-- SpringBoot基础依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Activiti集成 --> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>6.0.0</version> </dependency> <!-- 数据库支持 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> </dependencies>

1.2 数据库配置策略

Activiti引擎需要特定的数据库表结构支持,正确的初始化策略对系统稳定性至关重要。推荐采用以下配置组合:

配置项推荐值适用场景
spring.activiti.database-schema-updatetrue开发环境
spring.activiti.database-schema-updatefalse生产环境
spring.activiti.history-levelfull需要完整审计
# 开发环境配置示例 spring.datasource.url=jdbc:mysql://localhost:3306/activiti_demo spring.datasource.username=root spring.datasource.password=yourpassword spring.activiti.database-schema-update=true spring.activiti.history-level=full

提示:生产环境务必关闭database-schema-update,避免意外修改表结构

2. 流程建模与部署

2.1 BPMN2.0流程设计规范

请假审批流程通常包含以下核心节点:

  1. 开始事件:流程触发点
  2. 用户任务:请假申请节点
  3. 排他网关:根据请假天数路由
  4. 用户任务:部门审批节点(条件:天数>3)
  5. 结束事件:流程终止点
<!-- 简化版BPMN定义示例 --> <process id="vacationProcess" name="请假审批流程"> <startEvent id="startEvent"/> <userTask id="applyTask" name="请假申请"/> <exclusiveGateway id="decisionGateway"/> <sequenceFlow sourceRef="startEvent" targetRef="applyTask"/> <sequenceFlow sourceRef="applyTask" targetRef="decisionGateway"/> </process>

2.2 流程部署最佳实践

推荐采用资源目录自动部署方式,将流程定义文件放置在特定目录:

src/main/resources/processes/ ├── vacation-process.bpmn20.xml └── department-approval.bpmn20.xml

通过RepositoryService进行动态部署验证:

@Autowired private RepositoryService repositoryService; public void deployProcess() { Deployment deployment = repositoryService.createDeployment() .addClasspathResource("processes/vacation-process.bpmn20.xml") .name("请假流程部署") .deploy(); logger.info("流程部署成功,ID: {}", deployment.getId()); }

3. 系统集成与业务实现

3.1 用户体系整合方案

企业现有用户系统与Activiti身份管理的对接是关键挑战。推荐采用以下整合模式:

public void syncUserToActiviti(User user) { // 创建Activiti用户 User activitiUser = identityService.newUser(user.getId().toString()); activitiUser.setFirstName(user.getRealName()); activitiUser.setEmail(user.getEmail()); identityService.saveUser(activitiUser); // 同步角色关系 user.getRoles().forEach(role -> { Group group = identityService.createGroupQuery() .groupId(role.getId().toString()) .singleResult(); if (group == null) { group = identityService.newGroup(role.getId().toString()); group.setName(role.getName()); group.setType(role.getType()); identityService.saveGroup(group); } // 建立用户-组关系 identityService.createMembership( user.getId().toString(), role.getId().toString() ); }); }

3.2 业务数据与流程数据分离设计

遵循流程数据与业务数据分离原则,设计数据库表结构:

请假申请表结构示例

字段名类型描述
idBIGINT主键
process_instance_idVARCHAR流程实例ID
applicant_idBIGINT申请人ID
start_dateDATE开始日期
end_dateDATE结束日期
reasonVARCHAR请假原因

业务服务层实现流程启动逻辑:

public String startVacationProcess(VacationRequest request) { // 1. 保存业务数据 VacationApply apply = new VacationApply(); apply.setApplicantId(request.getUserId()); apply.setDays(request.getDays()); apply = vacationRepository.save(apply); // 2. 启动流程实例 Map<String, Object> variables = new HashMap<>(); variables.put("days", request.getDays()); variables.put("formId", apply.getId()); ProcessInstance instance = runtimeService.startProcessInstanceByKey( "vacationProcess", variables ); // 3. 关联业务与流程数据 apply.setProcessInstanceId(instance.getId()); vacationRepository.save(apply); return instance.getId(); }

4. 核心功能实现细节

4.1 动态任务查询与分页

结合Spring Data JPA实现高效的任务查询:

public Page<TaskDTO> getPendingTasks(Long userId, int page, int size) { // 获取用户所在角色组 List<String> groupIds = identityService.createGroupQuery() .groupMember(userId.toString()) .list() .stream() .map(Group::getId) .collect(Collectors.toList()); // 构建任务查询 TaskQuery query = taskService.createTaskQuery() .taskCandidateOrAssigned(userId.toString()) .taskCandidateGroupIn(groupIds) .orderByTaskCreateTime() .desc(); // 分页处理 List<Task> tasks = query.listPage((page-1)*size, size); long total = query.count(); // 转换为DTO List<TaskDTO> dtos = tasks.stream() .map(this::convertToDTO) .collect(Collectors.toList()); return new PageImpl<>(dtos, PageRequest.of(page-1, size), total); }

4.2 审批操作完整实现

审批服务需要处理多种业务场景:

@Transactional public void processApproval(ApprovalRequest request) { // 1. 验证任务有效性 Task task = taskService.createTaskQuery() .taskId(request.getTaskId()) .singleResult(); if (task == null) { throw new BusinessException("任务不存在或已完成"); } // 2. 保存审批意见 Approval approval = new Approval(); approval.setTaskId(task.getId()); approval.setComment(request.getComment()); approval.setResult(request.getResult()); approvalRepository.save(approval); // 3. 处理审批结果 Map<String, Object> variables = new HashMap<>(); variables.put("approvalResult", request.getResult()); if (request.getResult() == ApprovalResult.REJECT) { // 拒绝时终止流程 runtimeService.deleteProcessInstance( task.getProcessInstanceId(), "审批拒绝" ); } else { // 认领并完成任务 taskService.claim(task.getId(), request.getUserId().toString()); taskService.complete(task.getId(), variables); } }

4.3 流程可视化实现

生成带高亮的流程图需要特殊处理:

public void generateProcessImage(String processInstanceId, HttpServletResponse response) { try { // 获取BPMN模型 ProcessInstance instance = runtimeService.createProcessInstanceQuery() .processInstanceId(processInstanceId) .singleResult(); BpmnModel model = repositoryService.getBpmnModel( instance.getProcessDefinitionId() ); // 获取当前活动节点 List<String> activeIds = runtimeService.getActiveActivityIds(processInstanceId); // 生成图像流 InputStream imageStream = processEngine.getProcessEngineConfiguration() .getProcessDiagramGenerator() .generateDiagram( model, "png", activeIds, Collections.emptyList(), "宋体", "宋体", "宋体", null, 1.0 ); // 输出响应 response.setContentType("image/png"); IOUtils.copy(imageStream, response.getOutputStream()); } catch (Exception e) { logger.error("流程图生成失败", e); throw new RuntimeException("流程图生成失败"); } }

5. 生产环境注意事项

5.1 性能优化建议

针对高并发场景的配置调整:

# Activiti异步执行器配置 spring.activiti.async-executor-activate=true spring.activiti.async-executor-core-pool-size=10 spring.activiti.async-executor-max-pool-size=50 spring.activiti.async-executor-queue-capacity=1000

5.2 监控与日志方案

集成Spring Boot Actuator监控端点:

端点功能描述
/actuator/activiti流程引擎状态
/actuator/processes已部署流程
/actuator/tasks运行中任务统计

日志记录关键操作:

@Aspect @Component public class ActivitiLogAspect { @AfterReturning( pointcut = "execution(* org.activiti.engine..*.*(..))", returning = "result" ) public void logActivitiOperation(JoinPoint jp, Object result) { String operation = jp.getSignature().getName(); logger.info("Activiti操作 {} 执行成功,结果: {}", operation, result); } }

5.3 异常处理机制

统一异常处理增强系统健壮性:

@ControllerAdvice public class ActivitiExceptionHandler { @ExceptionHandler(ActivitiException.class) public ResponseEntity<ErrorResponse> handleActivitiError(ActivitiException e) { ErrorResponse response = new ErrorResponse(); response.setCode("ACTIVITI_ERROR"); response.setMessage(e.getMessage()); return ResponseEntity .status(HttpStatus.INTERNAL_SERVER_ERROR) .body(response); } @ExceptionHandler(ActivitiObjectNotFoundException.class) public ResponseEntity<ErrorResponse> handleNotFound(ActivitiObjectNotFoundException e) { return ResponseEntity .status(HttpStatus.NOT_FOUND) .body(new ErrorResponse("PROCESS_NOT_FOUND", e.getMessage())); } }

在项目实际部署中,我们发现流程定义的热更新是个常见需求。通过扩展RepositoryService可以实现不重启服务的流程版本更新,这对7×24小时运行的系统尤为重要。另外,建议对历史流程数据定期归档,避免核心表数据膨胀影响查询性能。

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

Excel用户零门槛上手Tableau:把BI变成Excel的超级外挂

1. 项目概述&#xff1a;当Excel老手第一次把鼠标拖进Tableau界面时&#xff0c;发生了什么&#xff1f;我带过三十多期数据分析实战训练营&#xff0c;学员里有财务总监、供应链经理、市场策划、高校教师&#xff0c;甚至还有刚毕业的文科生。但几乎所有人坐到电脑前的第一句问…

作者头像 李华
网站建设 2026/5/26 17:41:31

FPGA硬件加速器设计:HLS性能预测与自动化设计空间探索实践

1. 项目概述&#xff1a;FPGA硬件加速器设计的新范式如果你是一位算法工程师或者软件开发者&#xff0c;曾经对FPGA硬件加速望而却步&#xff0c;觉得那是一个需要精通Verilog/VHDL的“硬件专家”才能涉足的领域&#xff0c;那么今天的内容可能会彻底改变你的看法。过去十年&am…

作者头像 李华
网站建设 2026/5/26 17:38:11

FastAPI行级权限控制完整指南:为什么你需要fastapi-permissions

FastAPI行级权限控制完整指南&#xff1a;为什么你需要fastapi-permissions 【免费下载链接】fastapi-permissions row level security for FastAPI framework 项目地址: https://gitcode.com/gh_mirrors/fa/fastapi-permissions 在构建现代Web应用时&#xff0c;权限控…

作者头像 李华
网站建设 2026/5/26 17:36:04

403 Forbidden错误快速定位与根因诊断指南

1. 这不是网络问题&#xff0c;是权限门禁被触发了 你刷新页面&#xff0c;控制台突然炸出一行红字&#xff1a; Failed to load resource: the server responded with a status of 403 (Forbidden) 。紧接着&#xff0c;图片不显示、API调用失败、字体加载中断——整个页面像…

作者头像 李华
网站建设 2026/5/26 17:36:01

项目文档:基于STM32的蓝牙控制智能循迹避障小车设计与实现

摘要&#xff1a;随着智能控制技术的快速发展&#xff0c;智能小车作为移动机器人的典型应用&#xff0c;在教育、娱乐和工业领域得到了广泛关注。本文设计并实现了一种基于STM32F10x微控制器的蓝牙控制智能循迹避障小车系统。文档简介系统以STM32F103单片机为核心控制器&#…

作者头像 李华