环境:
jdk 1.8
maven 3.0
IDEA插件之actiBPM
springboot2.0
activiti6.0
mysql数据库
具体demo地址:https://download.csdn.net/download/qq_33333654/11790823
第一步、创建springbootweb项目
创建流程就不说了,自行百度吧。简单
第二步、集成activiti6.0
添加依赖
4.0.0 org.springframework.boot spring-boot-starter-parent 1.5.9.RELEASE com.example demo 0.0.1-SNAPSHOT demo Demo project for Spring Boot war 1.8 UTF-8 UTF-8 org.springframework.boot spring-boot-starter-web org.activiti activiti-spring-boot-starter-basic 6.0.0 org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-starter-test test org.activiti activiti-engine 6.0.0 org.slf4j slf4j-api 1.7.21 org.slf4j slf4j-log4j12 1.7.21 mysql mysql-connector-java 6.0.6 mysql mysql-connector-java org.springframework.boot spring-boot-starter-tomcat com.alibaba fastjson 1.2.41 org.projectlombok lombok 1.16.20 provided org.springframework.boot spring-boot-maven-plugin org.apache.tomcat.maven tomcat7-maven-plugin 8081 /activity 4000
上面是我所有的依赖。
yml文件配置
spring: activiti: check-process-definitions: true #自动检查、部署流程定义文件 database-schema-update: true #自动更新数据库结构 history-level: full #保存历史数据级别设置为full最高级别,便于历史数据的追溯 还有两个级别activity与none # process-definition-location-prefix: classpath:/processes/ #process-definition-location-suffixes: # - **.bpmn20.xml # - **.bpmn datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC username: root password: 123456
注意下,check-process-definitions这个后面是要修改值的。
在resources文件夹下创建processes文件夹。
创建日志文件log4j.properties
log4j.rootLogger=DEBUG, ACT log4j.appender.ACT=org.apache.log4j.ConsoleAppender log4j.appender.A1.Encoding=UTF-8 log4j.appender.ACT.layout=org.apache.log4j.PatternLayout log4j.appender.ACT.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n
启动类添加注解
@SpringBootApplication(exclude = SecurityAutoConfiguration.class) public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
启动项目,启动后刷新下数据库,可以看到28张act开头的数据库表,全部是activiti的表
第二步算是完成了。
第三步、绘制流程图
在processes文件夹下创建一个xml文件,文件内容如下:
复制该文件,并粘贴到当前文件夹,后缀名修改为bpmn。双击打开,如下图:
流程图绘制完成。
第四步:部署流程、启动流程、审批、结束流程。
首先,找到yml文件,修改
check-process-definitions的值为false
如下图,分别创建对应的文件夹和文件,等下会挨个粘贴代码
参考文献:https://yq.aliyun.com/articles/697485
model的leave
package com.example.demo.model; import lombok.Data; import java.io.Serializable; import java.util.Date; /** * @ProjectName: demo * @Package: com.example.demo.service.model * @ClassName: Leave * @Author: MC * @Description: ${description} * @Date: 2019/9/19 0019 13:14 * @Version: 1.0 */ @Data public class Leave implements Serializable { private static final long serialVersionUID = 2248469053125414262L; private String userId; private Boolean submit; private Date startDate; private Date endDate; private float totalDay; private String desc; private String taskId; private String taskName; private String approver1; private Boolean agree1; private String approveDesc1; private String approver2; private Boolean agree2; private String approveDesc2; }
ActivitiUtil
package com.example.demo.utils; import org.activiti.bpmn.model.*; import org.activiti.bpmn.model.Process; import org.activiti.engine.ProcessEngine; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.history.HistoricActivityInstance; import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.history.HistoricVariableInstance; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.*; /** * @ProjectName: demo * @Package: com.example.demo.utils * @ClassName: ActivitiUtil * @Author: MC * @Description: ${description} * @Date: 2019/9/19 0019 18:17 * @Version: 1.0 */ @Service public class ActivitiUtil { @Autowired private ProcessEngine processEngine; @Autowired private RuntimeService runtimeService ; @Autowired private TaskService taskService ; @Autowired private RepositoryService repositoryService; /** * @Method 部署流程 * @Author MC * @Return * @Date 2019/9/19 0019 18:34 */ public void deploy(String filePath){ if(!StringUtils.isEmpty(filePath)){ repositoryService.createDeployment() .addClasspathResource(filePath) .deploy(); } } /** * @Method 启动流程 * @Author MC * @Return * @Date 2019/9/19 0019 18:35 */ public Map
start(Map map ,String processId){ ProcessInstance leave1 = runtimeService.startProcessInstanceByKey(processId, map); String processDefinitionId = leave1.getProcessDefinitionId(); System.out.print("============processDefinitionId:" + processDefinitionId);//流程定义的ID System.out.print("============processInstanceId:" + leave1.getId());//流程实例的ID Map resultMap = new HashMap<>(); resultMap.put("result",leave1); resultMap.put("processDefinitionId",processDefinitionId); resultMap.put("processInstanceId",leave1.getId()); return resultMap; } /** * @Method 根据流程实例ID和用户ID查询任务ID * @Author MC 用户ID必须设置为Assignee * @Return * @Date 2019/9/19 0019 19:01 */ public String getTaskId( String processInstanceId, String userId){ TaskService taskService = processEngine.getTaskService();//获取任务的Service,设置和获取流程变量 //查询当前办理人的任务ID Task task = taskService.createTaskQuery() .processInstanceId(processInstanceId)//使用流程实例ID .taskAssignee(userId)//任务办理人 .singleResult(); return task.getId(); } /** * @Method 获取流程实例列表 * @Author MC * @Return * @Date 2019/9/19 0019 18:32 */ public List queryProcessInstanceAllList(String processDefinitionKey){ return runtimeService .createProcessInstanceQuery().processDefinitionKey(processDefinitionKey) .list(); } /** * @Method 根据assignee来查询用户 * @Author MC * @Return * @Date 2019/9/19 0019 18:29 */ public Task queryTask(String assignee) { //startProcessInstance(); // taskService.createTaskQuery().taskCandidateGroup("sales").singleResult(); Task task= taskService.createTaskQuery().taskAssignee(assignee).singleResult(); if(task == null){ return null; } System.out.println("审批人为【"+assignee+"】的任务有:任务编号为【" + task.getId() + "】"+ task.getTaskDefinitionKey()); return task; } /** * * @param queryType 查询类型1 根据 assignee 查询 2 根据candidateuser查询 * @param str */ public String getNextNodeId(int queryType,String str) { Task task = null; if(queryType==1) { task = taskService.createTaskQuery().taskAssignee(str).singleResult(); }else if(queryType==2){ task = taskService.createTaskQuery().taskCandidateUser(str).singleResult(); }else if(queryType==3){ task = taskService.createTaskQuery().taskCandidateGroup(str).singleResult(); } // List list = getNextNode(task.getId()); if(task==null) { return null; } // for(FlowElement e :list) { // //((org.activiti.bpmn.model.UserTask) e) // } return task.getId(); } /** * 获取流程的下一个节点 且要经过规则引擎判断后的节点 * @param taskId * @return */ private List getNextNode(String taskId) { Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); if(task==null) { return null; } List list = new ArrayList (); ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult(); //当前活动节点 String activitiId = processInstance.getActivityId(); System.out.println("当前节点是【"+activitiId+"】"); //pmmnModel 遍历节点需要它 BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId()); List processList = bpmnModel.getProcesses(); //循环多个物理流程 for(Process process:processList) { //返回该流程的所有任务,事件 Collection cColl = process.getFlowElements(); //遍历节点 for(FlowElement f :cColl) { //如果改节点是当前节点 者 输出该节点的下一个节点 if(f.getId().equals(activitiId)) { List sequenceFlowList = new ArrayList (); //通过反射来判断是哪种类型 if(f instanceof org.activiti.bpmn.model.StartEvent) { //开始事件的输出路由 sequenceFlowList = ((org.activiti.bpmn.model.StartEvent) f).getOutgoingFlows(); }else if(f instanceof org.activiti.bpmn.model.UserTask) { sequenceFlowList = ((org.activiti.bpmn.model.UserTask) f).getOutgoingFlows(); for(SequenceFlow sf :sequenceFlowList) { String targetRef = sf.getTargetRef(); FlowElement ref = process.getFlowElement(targetRef); // nextActivitiIdList.add(ref.getId()); list.add(ref); } }else if(f instanceof org.activiti.bpmn.model.SequenceFlow) { }else if(f instanceof org.activiti.bpmn.model.EndEvent) { sequenceFlowList = ((org.activiti.bpmn.model.EndEvent) f).getOutgoingFlows(); } break; } } } return list; } /** * @Method 流程流转到下一步 * @Author MC 根据 assignee 查询出任务,如果存在则设置当前任务的 assignee 为 nextUser * @Return 不存在下一个节点返回false; * @Date 2019/9/19 0019 18:23 */ public boolean completeByAssignee(String assignee,String nextUser) throws Exception { HashMap map = new HashMap (); map.put("nextUser", nextUser); Task task = taskService.createTaskQuery().taskAssignee(assignee).singleResult(); if(task == null){ System.out.println("下一节点不存在"); return false; } taskService.complete(task.getId(),map); System.out.println("完成任务 编号为【" + task.getId() + "】,名称为【"+task.getName()+"】的任务"); return true; } /** * 设置某个节点的审批人员 * @param taskId * @param user */ public void setApproveUser(String taskId,String user) { Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); task.setAssignee(user); taskService.saveTask(task); } /** * 取下一个节点的审批人 * @param taskId * @return */ public List getNextTaskUserByTaskId(String taskId) { List list = new ArrayList (); List fList = getNextNode(taskId); for(FlowElement u:fList){ String str = ((org.activiti.bpmn.model.UserTask) u).getAssignee(); list.add(str); } return list ; } /** * 找当前节点的候选审批人 供流程实例start后调用 * @param taskId * @return */ public List getThisTaskUser(String taskId) { List list = new ArrayList (); Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); String taskUser = task.getAssignee(); //*****************************根据taskUser的配置到自己的表里面去找数据 list.add(taskUser); return list ; } /** * @Method 任务是否完结 * @Author MC * @Return * @Date 2019/9/20 0020 11:20 */ public boolean isOverTask(String processInstanceId){ ProcessInstance pi= runtimeService.createProcessInstanceQuery() // 创建流程实例查询 .processInstanceId(processInstanceId) // 用流程实例id查询 .singleResult(); if(pi!=null){ System.out.println("流程正在执行!"); return false; }else{ System.out.println("流程已经执行结束!"); } return true; } /** * @Method 历史流程实例查询 * @Author MC * @Return * @Date 2019/9/20 0020 11:22 */ public List queryHisProInstance(String processDefinitionKey){ List historicProcessInstanceList = processEngine.getHistoryService().createHistoricProcessInstanceQuery() .processDefinitionKey(processDefinitionKey) .orderByProcessInstanceEndTime() .desc() .list(); /*for(HistoricProcessInstance historicProcessInstance:historicProcessInstanceList){ System.out.println("历史流程实例id: "+historicProcessInstance.getId()); System.out.println("历史流程实例的完成时间: "+historicProcessInstance.getEndTime()); }*/ return historicProcessInstanceList; } /** * 查询历史流程变量 */ public List queryHisProVariable(String processInstanceId){ List historicVariableInstanceList = processEngine.getHistoryService() .createHistoricVariableInstanceQuery() .processInstanceId(processInstanceId).list(); /*for(HistoricVariableInstance historicVariableInstance: historicVariableInstanceList){ System.out.println("历史流程变量id: "+historicVariableInstance.getId()); System.out.println("历史流程变量名称: "+historicVariableInstance.getVariableName()); System.out.println("历史流程变量值: "+historicVariableInstance.getValue()); System.out.println("=================================================="); }*/ return historicVariableInstanceList; } /** * 根据办理人查询历史任务实例 */ public List queryHisTaskInstanceByAssignee(String processDefinitionKey,String taskAssignee){ List historicTaskInstanceList = processEngine.getHistoryService().createHistoricTaskInstanceQuery() .processDefinitionKey(processDefinitionKey) .taskAssignee(taskAssignee).list(); /*for(HistoricTaskInstance historicTaskInstance:historicTaskInstanceList){ System.out.println("历史任务id: "+historicTaskInstance.getId()); System.out.println("历史任务名称: "+historicTaskInstance.getName()); System.out.println("历史任务结束时间: "+historicTaskInstance.getEndTime()); System.out.println("办理人: "+historicTaskInstance.getAssignee()); System.out.println("=================================================="); }*/ return historicTaskInstanceList; } /** * 历史任务查询 * type: 0:未完成 1:已完成 "":all */ public List historyTaskList(String processInstanceId,String type){ List list=null; if(StringUtils.isEmpty(type)){ list = processEngine.getHistoryService() // 历史相关Service .createHistoricTaskInstanceQuery() // 创建历史任务实例查询 .processInstanceId(processInstanceId) // 用流程实例id查询 .list(); }else if("0".equals(type)){ list = processEngine.getHistoryService() // 历史相关Service .createHistoricTaskInstanceQuery() // 创建历史任务实例查询 .processInstanceId(processInstanceId) // 用流程实例id查询 .unfinished() .list(); }else if("1".equals(type)){ processEngine.getHistoryService() // 历史相关Service .createHistoricTaskInstanceQuery() // 创建历史任务实例查询 .processInstanceId(processInstanceId) // 用流程实例id查询 .finished() // 查询已经完成的任务 .list(); } /* for(HistoricTaskInstance hti:list){ System.out.println("任务ID:"+hti.getId()); System.out.println("流程实例ID:"+hti.getProcessInstanceId()); System.out.println("任务名称:"+hti.getName()); System.out.println("办理人:"+hti.getAssignee()); System.out.println("开始时间:"+hti.getStartTime()); System.out.println("结束时间:"+hti.getEndTime()); System.out.println("================================="); }*/ return list; } /** * 已完成的历史活动查询 */ public List historyActInstanceList(String processInstanceId){ List list=processEngine.getHistoryService() // 历史相关Service .createHistoricActivityInstanceQuery() // 创建历史活动实例查询 .processInstanceId(processInstanceId) // 执行流程实例id .finished() .list(); /* for(HistoricActivityInstance hai:list){ System.out.println("活动ID:"+hai.getId()); System.out.println("流程实例ID:"+hai.getProcessInstanceId()); System.out.println("活动名称:"+hai.getActivityName()); System.out.println("办理人:"+hai.getAssignee()); System.out.println("开始时间:"+hai.getStartTime()); System.out.println("结束时间:"+hai.getEndTime()); System.out.println("================================="); }*/ return list; } }
LeaveController
package com.example.demo.web; import com.example.demo.model.Leave; import com.example.demo.utils.ActivitiUtil; import org.activiti.engine.*; import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.history.HistoricVariableInstance; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @ProjectName: demo * @Package: com.example.demo.web * @ClassName: LeaveController * @Author: MC * @Description: ${description} * @Date: 2019/9/19 0019 13:08 * @Version: 1.0 */ @RestController @RequestMapping("/level/v1") public class LeaveController { public static final Logger log = LoggerFactory.getLogger(LeaveController.class); @Autowired private ProcessEngine processEngine; @Autowired private RuntimeService runtimeService ; @Autowired private TaskService taskService ; @Autowired private RepositoryService repositoryService; @Autowired private ActivitiUtil activitiUtil; /** * @Method 部署流程 * @Author MC * @Return * @Date 2019/9/19 0019 17:07 */ @RequestMapping(value = "/deploy",method = RequestMethod.GET) public Map
deploy(){ repositoryService.createDeployment() .addClasspathResource("processes/leave1.bpmn") .deploy(); List list = repositoryService.createProcessDefinitionQuery().list(); for (int i = 0; i < list.size(); i++) { ProcessDefinition p = list.get(i); System.out.print("============key:"+p.getKey()); } Map map = new HashMap<>(); map.put("list",list); return map; } /** * @Method 根据userId启动流程 * @Author MC * @Return * @Date 2019/9/19 0019 13:23 */ @RequestMapping(value = "/start",method = RequestMethod.GET) public Map start(@RequestParam String userId){ Map map = new HashMap<>(); Leave leave = new Leave(); leave.setUserId(userId); map.put("leave",leave); ProcessInstance leave1 = runtimeService.startProcessInstanceByKey("leave1", map); String processDefinitionId = leave1.getProcessDefinitionId(); System.out.print("============processDefinitionId:" + processDefinitionId);//流程定义的ID System.out.print("============processInstanceId:" + leave1.getId());//流程实例的ID Map resultMap = new HashMap<>(); resultMap.put("result",leave1); resultMap.put("processDefinitionId",processDefinitionId); resultMap.put("processInstanceId",leave1.getId()); return resultMap; } @RequestMapping(value = "/selectUser",method = RequestMethod.GET) public String selectUser() throws Exception { String taskId = activitiUtil.getTaskId("5005", "feng"); List userList= activitiUtil.getNextTaskUserByTaskId(taskId); //设置审批人 activitiUtil.setApproveUser(taskId, "12321"); taskId = activitiUtil.getNextNodeId(1,"feng"); //第一个审批人提交流程 feng 为当前节点审批人,xiaozhang 为设置的下一节点审批人 boolean b = activitiUtil.completeByAssignee("feng","xiaozhang"); //************第一个人审批成功 if(b){ //TODO } // taskId = activitiUtil.getNextNodeId(1,"xiaozhang"); // //选人 // userList= activitiUtil.getNextTaskUserByTaskId(taskId); // //第一个审批人提交流程 // activitiUtil.completeByAssignee("xiaozhang","xiaoming"); // // activitiUtil.getNextNodeId(1,"xiaoming"); // // //第二个审批人提交流程 // activitiUtil.completeByAssignee("xiaoming","xiangwang"); //************第二个人审批成功 return ""; } /** * @Method 根据流程实例ID和任务办理人其实就是Assignee获取任务task实例 * @Author MC * @Return * @Date 2019/9/19 0019 13:45 */ @RequestMapping(value = "/task",method = RequestMethod.GET) public String task(@RequestParam String processInstanceId,@RequestParam String userId){ //查询当前办理人的任务ID Task task = taskService.createTaskQuery() .processInstanceId(processInstanceId)//使用流程实例ID .taskAssignee(userId)//任务办理人 .singleResult(); return task.getId(); } /** * @Method 填写请假表单 * @Author MC * @Return * @Date 2019/9/19 0019 13:45 */ @RequestMapping(value = "/apply",method = RequestMethod.POST) public Map apply(@RequestBody Leave leave){ String taskId = leave.getTaskId(); Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); Map map = new HashMap<>(); // 获取流程参数 对应启动流程时,入参的参数leave Leave variable = (Leave)taskService.getVariable(taskId, "leave"); // 从入参的表单对象中取值,设置流程参数对象的值 variable.setDesc(leave.getDesc()); variable.setStartDate(leave.getStartDate()); variable.setTotalDay(leave.getTotalDay()); variable.setApprover1(leave.getApprover1()); variable.setSubmit(leave.getSubmit()); map.put("leave",variable); taskService.complete(taskId,map); // Map resultMap = ResultMapHelper.getSuccessMap(); Map resultMap = new HashMap<>(); resultMap.put("leave",leave); return resultMap; } /** * @Method 根据用户ID查询流程集合 * @Author MC * @Return * @Date 2019/9/19 0019 13:52 */ @RequestMapping(value = "/find",method = RequestMethod.GET) public Map find(@RequestParam("userId") String userId){ List list = taskService.createTaskQuery().taskAssignee(userId).list(); List resultList = new ArrayList<>(); if(!CollectionUtils.isEmpty(list)){ for (Task t : list) { Leave leave = (Leave)taskService.getVariable(t.getId(),"leave"); leave.setTaskId(t.getId()); leave.setTaskName(t.getName()); resultList.add(leave); } } Map resultMap = new HashMap<>(); resultMap.put("resultList",resultList); return resultMap; } /** * 直接主管审批 * @param leave * @return */ @RequestMapping(value = "/approve1", method = RequestMethod.POST) public Map approve1(@RequestBody Leave leave){ Task task = taskService.createTaskQuery().taskId(leave.getTaskId()).singleResult(); Map vars = new HashMap<>(); Leave origin = (Leave) taskService.getVariable(leave.getTaskId(), "leave"); origin.setApproveDesc1(leave.getApproveDesc1()); origin.setAgree1(leave.getAgree1()); origin.setApprover2(leave.getApprover2()); vars.put("leave", origin); taskService.complete(leave.getTaskId(),vars);//设置完以后会发现run_task表中的Assignee字段为空。。。。 Map resultMap = new HashMap<>(); resultMap.put("leave", origin); return resultMap; } /** * 部门主管审批 * @param leave * @return */ @RequestMapping(value = "/approve2", method = RequestMethod.POST) public Map approve2(@RequestBody Leave leave){ Task task = taskService.createTaskQuery().taskId(leave.getTaskId()).singleResult(); Map vars = new HashMap<>(); Leave origin = (Leave) taskService.getVariable(leave.getTaskId(), "leave"); origin.setApproveDesc2(leave.getApproveDesc2()); origin.setAgree2(leave.getAgree2()); vars.put("leave", origin); taskService.complete(leave.getTaskId(),vars); Map resultMap = new HashMap<>(); resultMap.put("leave", origin); return resultMap; } /** * 查看历史记录 * @param userId * @return */ @RequestMapping(value="/findClosed", method = RequestMethod.GET) public Map findClosed(@RequestParam String userId){ // HistoryService historyService = processEngine.getHistoryService(); List leaves = new ArrayList<>(); List historicProcessInstanceList = activitiUtil.queryHisProInstance("leave1"); for(HistoricProcessInstance historicProcessInstance:historicProcessInstanceList){ System.out.println("历史流程实例id: "+historicProcessInstance.getId()); System.out.println("历史流程实例的完成时间: "+historicProcessInstance.getEndTime()); leaves.add((Leave) historicProcessInstance.getProcessVariables().get("leave")); } // 注意:这一段为什么获取不到数据?哪位能帮忙解决下? List list = processEngine.getHistoryService().createHistoricProcessInstanceQuery(). processDefinitionKey("leave1") .variableValueEquals("leave.userId",userId).list(); List historicVariableInstanceList = activitiUtil.queryHisProVariable("5005"); for(HistoricVariableInstance historicVariableInstance: historicVariableInstanceList){ System.out.println("历史流程变量id: "+historicVariableInstance.getId()); System.out.println("历史流程变量名称: "+historicVariableInstance.getVariableName()); System.out.println("历史流程变量值: "+historicVariableInstance.getValue()); System.out.println("=================================================="); } Map resultMap = new HashMap<>(); resultMap.put("datas", leaves); return resultMap; } }
第四步操作完成。
接下来启动项目,观察数据库内容的变化,并按照绘制的流程图调用相关的接口,观察数据库的变化。
以上内容属于入门篇,仅供参考。