# SpringBoot+Activiti **Repository Path**: wangfugui-ma/spring-boot-activiti ## Basic Information - **Project Name**: SpringBoot+Activiti - **Description**: springboot集成activiti实现流程的创建,审批,查询,历史记录等功能 - **Primary Language**: Java - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 12 - **Forks**: 9 - **Created**: 2021-12-02 - **Last Updated**: 2026-04-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: SpringBoot, activiti ## README ## 啦啦啦啦啦,富贵同学又开始开坑了,出了个免费的专栏,主要给大家从0基础开始用springBoot集成第三方的插件或者功能,如果这篇专栏能帮到你,一定不要忘了点一个赞哦!!欢迎大家收藏分享 ![在这里插入图片描述](img/4be87571889b84aebd56911ec1000b9b.jpeg#pic_center) ## 第一步,导入jar包 ```java org.activiti activiti-spring-boot-starter-basic 5.22.0 ``` 这是activiti的核心包,我们还添加其他的jar包 ```java org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-web mysql mysql-connector-java 5.1.30 ``` ## 第二步,编写配置文件 ```java server: port: 8089 spring: datasource: url: jdbc:mysql://localhost:3306/activiti driver-class-name: com.mysql.jdbc.Driver username: root password: 123456 ``` ## 第三步,创建activiti库 ![在这里插入图片描述](img/7548e1500dd2a553a3e75b40920b894e.png) ## 第四步,运行启动类 ![在这里插入图片描述](img/c0a07d7cb036489d29ba9ad00a61ef17.png) 好,遇到这个时候就出现问题了,这是富贵同学替大家踩坑了,大家记得避开 **启动报错Could not find class [org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration]** 这个问题是activiti里面本身会依赖Security,所以我们将他排除,我们在启动类上加上 ```java exclude = SecurityAutoConfiguration.class ``` ![在这里插入图片描述](img/0faaa2c013de7f47b61792928f72d825.png) 好的,我们启动,这个时候又碰见另外的一个问题 **Caused by: java.io.FileNotFoundException: class path resource [processes/] cannot be resolved to URL because it does not exist** 这个是因为activiti在启动的时候会去找bpm文件,会去到默认的processes文件夹中找, 这个时候我们在配置类中加入 ```java activiti: check-process-definitions: false ``` ![在这里插入图片描述](img/77ac1a225fd60432e6efbd346e2144fb.png) 这个时候就启动成功啦! ![在这里插入图片描述](img/79b8a96b3b517972c1546d9dfaa02beb.png) ## 第五步.启动成功之后查看我们的数据库 ![在这里插入图片描述](img/76f3f75ee6ba725ea97c252fb743b029.png) 就会发现25张表已经自动生成了! 如果没有看过富贵同学的第一篇请移步到这个地址查看[SpringBoot集成Activiti(一)](https://blog.csdn.net/csdnerM/article/details/121680351) 第一步,取消yml的配置,因为我们需要创建一个流程 ![在这里插入图片描述](img/9cfe2b6dfa9f4b473cf50a4a973a9e94.png) `leave.bpmn`文件感谢(https://gitee.com/shenzhanwang/Spring-activiti)提供的流程文件 ```java ``` 这是一个简单的请假申请流程 ## 第六步,放入指定的文件夹中之后,我们重新启动启动类 ## 第七步,查看我们的数据表 `ACT_RE_PROCDEF`中可以查看到我们的流程 ![在这里插入图片描述](img/3bb4ca456cdbc3dfa9c8fb54d7f7670b.png) 至此之后我们的流程就创建完成了,现在来我们的api操作 ## 第八步,由于我们要跟我们的业务连接到一起,所以我们创建一个请假表 ```java CREATE TABLE `leave` ( `id` int(11) NOT NULL AUTO_INCREMENT, `process_instance_id` varchar(45) DEFAULT NULL COMMENT '流程表id', `user_id` varchar(20) DEFAULT NULL COMMENT '用户id', `start_time` varchar(45) DEFAULT NULL COMMENT '开始时间', `end_time` varchar(45) DEFAULT NULL COMMENT '结束时间', `leave_type` varchar(45) DEFAULT NULL COMMENT '请假类型', `reason` varchar(400) DEFAULT NULL COMMENT '请假原因', `apply_time` datetime DEFAULT NULL COMMENT '通过时间', `reality_start_time` varchar(45) DEFAULT NULL COMMENT '请假开始时间', `reality_end_time` varchar(45) DEFAULT NULL COMMENT '请假结束时间', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='请假表'; ``` ![在这里插入图片描述](img/1f2b83355cd6481b1fe9684bf41dcd8b.png) ## 第九步,集成底层框架 对了,我们没有数据库框架,这里我们使用[mybatisPlusPro](https://blog.csdn.net/csdnerM/article/details/121565202)来作为底层框架 ## 第十步,创建controller等类 ```java import com.wangfugui.activiti.dao.LeaveDO; import com.wangfugui.activiti.service.LeaveService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author MaSiyi * @version 1.0.0 2021/12/2 * @since JDK 1.8.0 */ @RestController @RequestMapping("/leave") public class LeaveController extends BaseController{ } ``` ```java import com.baomidou.mybatisplus.extension.service.IService; import com.wangfugui.activiti.dao.LeaveDO; /** * @author MaSiyi * @version 1.0.0 2021/12/2 * @since JDK 1.8.0 */ public interface LeaveService extends IService { } ``` ```java import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.wangfugui.activiti.dao.LeaveDO; import com.wangfugui.activiti.dao.mapper.LeaveMapper; import com.wangfugui.activiti.service.LeaveService; import org.springframework.stereotype.Service; /** * @author MaSiyi * @version 1.0.0 2021/12/2 * @since JDK 1.8.0 */ @Service public class LeaveServiceImpl extends ServiceImpl implements LeaveService { } ```java hellow啊,靓仔,有没有看过前面的内容啊? 请移步到前面的内容去看(一)(二)的内容 接下来我们开始和我们的业务结合到一起。 ``` 还是先回顾一下上期内容,上期有个遗留的问题,就是mabatis jar包会冲突,所以我们 ```java org.activiti activiti-spring-boot-starter-basic 5.22.0 org.mybatis mybatis ``` ## 第十一步,好的,为了接下来方便接口的测试,我们使用swagger来快速搭建 ```java io.springfox springfox-swagger2 2.7.0 io.springfox springfox-swagger-ui 2.7.0 ``` ## 第十二步,编写controller类 ```java import com.wangfugui.activiti.dao.LeaveVo; import com.wangfugui.activiti.dao.Leaves; import com.wangfugui.activiti.dao.dto.HandleDto; import com.wangfugui.activiti.dao.dto.UpcomingDto; import com.wangfugui.activiti.service.LeaveService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * @author MaSiyi * @version 1.0.0 2021/12/2 * @since JDK 1.8.0 */ @RestController @RequestMapping("/leave") @Api(tags = "请假") public class LeaveController { @Autowired protected LeaveService leaveService; @PostMapping("/startLeave") @ApiOperation("发起一个请假流程") public String startLeave(@RequestBody Leaves leave) { return leaveService.startLeave(leave); } @PostMapping("/upcoming") @ApiOperation("获取待办列表") public List listTask(@RequestBody UpcomingDto upcomingDto) { return leaveService.upcoming(upcomingDto); } @PostMapping("/handle") @ApiOperation("处理流程") public String handle(@RequestBody HandleDto handleDto) { return leaveService.handle(handleDto); } } ``` 这次我们先来个简单的创建流程,获取待办流程,审批流程 所以我们就看到了这三个接口 ## 第十三步,我们进入到实现类中查看 ```java import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.wangfugui.activiti.dao.LeaveVo; import com.wangfugui.activiti.dao.Leaves; import com.wangfugui.activiti.dao.dto.HandleDto; import com.wangfugui.activiti.dao.dto.UpcomingDto; import com.wangfugui.activiti.dao.mapper.LeaveMapper; import com.wangfugui.activiti.service.LeaveService; import org.activiti.engine.IdentityService; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; /** * @author MaSiyi * @version 1.0.0 2021/12/2 * @since JDK 1.8.0 */ @Service public class LeaveServiceImpl extends ServiceImpl implements LeaveService { @Autowired private RuntimeService runtimeservice; @Autowired private IdentityService identityservice; @Autowired private TaskService taskservice; /** * 开启一个流程 * * @param leave * @Param: [leave] * @return: org.activiti.engine.runtime.ProcessInstance * @Author: MaSiyi * @Date: 2021/12/3 */ @Override public String startLeave(Leaves leave) { leave.setId(UUID.randomUUID().toString().substring(0, 8)); //设置用户 identityservice.setAuthenticatedUserId(leave.getUserId()); //使用leaveapply表的主键作为businesskey,连接业务数据和流程数据 String businesskey = String.valueOf(leave.getId()); //发起请假流程 Map map = new HashMap<>(); //下个步骤处理人 map.put("deptleader", "Tom"); ProcessInstance processInstance = runtimeservice.startProcessInstanceByKey("leave", businesskey, map); String instanceid = processInstance.getId(); //关联流程表 leave.setProcessInstanceId(instanceid); this.save(leave); return "申请成功"; } /** * 获取待办列表 * * @param upcomingDto * @Param: [upcomingDto] * @return: java.util.List * @Author: MaSiyi * @Date: 2021/12/3 */ @Override public List upcoming(UpcomingDto upcomingDto) { List leaves = new ArrayList<>(); // 使用任务候选人查询待办列表 List tasks = taskservice.createTaskQuery().taskAssignee(upcomingDto.getUsername()).taskName("部门领导审批") .listPage(upcomingDto.getPage(), upcomingDto.getSize()); for (Task task : tasks) { String instanceId = task.getProcessInstanceId(); //查询正在运行的task ProcessInstance processInstance = runtimeservice.createProcessInstanceQuery().processInstanceId(instanceId).singleResult(); String businessKey = processInstance.getBusinessKey(); Leaves leave = this.getById(businessKey); LeaveVo leaveVo = new LeaveVo(); BeanUtils.copyProperties(leave,leaveVo); leaveVo.setTaskId(task.getId()); leaves.add(leaveVo); } return leaves; } /** * 审批任务 * @Param: [taskid] * @return: java.lang.String * @Author: MaSiyi * @Date: 2021/12/3 */ @Override public String handle(HandleDto handleDto) { //完成指定任务 taskservice.claim(handleDto.getTaskId(), handleDto.getUserName()); //进行下一个任务 Map variables = new HashMap(); variables.put("deptleaderapprove", handleDto.getApprove()); variables.put("hr", handleDto.getNextUserNam()); taskservice.complete(handleDto.getTaskId(), variables); return "处理成功"; } } ``` 这三个的解释已经写在代码里面啦,大家可以去看看注释 ## 第十四步,我们来看一下我们的测试 发起一个流程 ![在这里插入图片描述](img/6dde3607e17fda591eb5c25fbe04aeb4.png) ![在这里插入图片描述](img/eadbcc76e7823908a0b9d590f985c6c8.png) 查询我们的待办 ![在这里插入图片描述](img/bfbc33f33cbd6fe4b6d9d5ada46dfbf8.png) ![在这里插入图片描述](img/58654c5ecb236eb58f25c73d7a9f3229.png) 处理我们的待办 ![在这里插入图片描述](img/c1f90f7e6b4ea4a58a1c4d1b64391ed0.png) ![在这里插入图片描述](img/34944d96e95ebcbfe1574d12648c9d6c.png) 好了,今天的简单的基本方法就到这里了 下一篇介绍查看历史流程等的集成 今天我们来讲一下历史流程 ## 第十五步首先我们要知道activiti中历史Service是`HistoryService` 所以我们第一步就将`HistoryService`注入进来 ![在这里插入图片描述](img/3ebdeb8e1d528b94466547335b19313a.png) ## 第十六步,编写获取历史流程方法 ```java @GetMapping("/myleave") @ApiOperation("我发起的请假流程") public List myleave(@RequestParam String userId) { return leaveService.myleave(userId); } ``` 这个接口是根据userId获取发起的请假流程 ```java @GetMapping("/getHistory") @ApiOperation("获取历史流程信息") public HistoricProcessInstance getHistory(@RequestParam String procInstId) { return leaveService.getHiProcByProcInstId(procInstId); } ``` 这个接口是什么呢 `procInstId`又是什么? ![在这里插入图片描述](img/4ff95921839b3e4477b854777133db0a.png) ![在这里插入图片描述](img/2bea139d04690d887015a676ac05330e.png) 第三个接口 ```java @GetMapping("/getHiProcByProcKeyAndBusinessID") @ApiOperation("获取历史任务") public HistoricProcessInstance getHiProcByProcKeyAndBusinessID(@RequestParam String procKey, @RequestParam String businessID) { return leaveService.getHiProcByProcKeyAndBusinessID(procKey, businessID); } ``` procKey和businessID又是什么? ![在这里插入图片描述](img/2a9ec5a40a3e2cf0a3efd11e9dcb9849.png) businessID是我们的业务主键 ![在这里插入图片描述](img/2b61729cde172882ecbfe26d1cc97ba0.png) 关联在这张表中 ![在这里插入图片描述](img/c58cdd261260cb4693f39459b3647782.png) ![在这里插入图片描述](img/3f6a26d8cdc1a6c1bf7b0769567d1fee.png) 好了,富贵同学手敲不容易,整整两万个字符,希望能帮助到大家。完整代码请移至[SpringBoot+Activiti ](https://gitee.com/WangFuGui-Ma/spring-boot-activiti)查看 希望大家点个赞和关注,谢谢大家 ![在这里插入图片描述](img/ea5524110aaec7fbe895af1210942941.jpeg#pic_center)