工作中需要使用到activiti工作流引擎,于是在业余时间学习activiti相关的内容,今天分享一个使用activiti来实现的请假流程,其中涉及分支条件的判断和表单的填写,下面就来分享下这个简单程序的内容。
环境搭建
使用maven来搭建工程,需要依赖如下:
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.197</version>
</dependency>
</dependencies>
使用h2数据库的原因是activiti的默认数据库就是H2,方便简单测试,此处加上h2的驱动。
流程图设计
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1536107421286" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="second_approve" isClosed="false" isExecutable="true" name="二级审批" processType="None">
<startEvent id="startEvent" name="开始"/>
<userTask activiti:exclusive="true" id="submitForm" name="填写审批信息">
<extensionElements>
<activiti:formProperty id="message" name="申请信息" required="true" type="string"/>
<activiti:formProperty id="name" name="申请人姓名" required="true" type="string"/>
<activiti:formProperty datePattern="yyyy-MM-dd" id="submitTime" name="提交时间" required="true" type="date"/>
<activiti:formProperty id="submitType" name="提交类型" required="true" type="string"/>
</extensionElements>
</userTask>
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="submitForm"/>
<exclusiveGateway gatewayDirection="Unspecified" id="decideSubmit" name="提交或取消"/>
<sequenceFlow id="flow2" sourceRef="submitForm" targetRef="decideSubmit"/>
<userTask activiti:exclusive="true" id="tl_approve" name="主管审批">
<extensionElements>
<activiti:formProperty id="tlApprove" name="主管审批结果" type="string"/>
<activiti:formProperty id="tlMessage" name="主管备注" required="true" type="string"/>
</extensionElements>
</userTask>
<sequenceFlow id="flow3" sourceRef="decideSubmit" targetRef="tl_approve">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${submitType == "y" || submitType == "Y"}]]></conditionExpression>
</sequenceFlow>
<exclusiveGateway gatewayDirection="Unspecified" id="decideTLApprove" name="主管审批校验"/>
<sequenceFlow id="flow4" sourceRef="tl_approve" targetRef="decideTLApprove"/>
<userTask activiti:exclusive="true" id="hr_approve" name="人事审批">
<extensionElements>
<activiti:formProperty id="hrApprove" name="人事审批结果" required="true" type="string"/>
<activiti:formProperty id="hrMessage" name="人事审批备注" required="true" type="string"/>
</extensionElements>
</userTask>
<sequenceFlow id="flow5" sourceRef="decideTLApprove" targetRef="hr_approve">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${tlApprove == "y" || tlApprove == "Y"}]]></conditionExpression>
</sequenceFlow>
<endEvent id="endEventCancel" name="取消"/>
<sequenceFlow id="flow7" sourceRef="decideSubmit" targetRef="endEventCancel">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${submitType == "n" || submitType == "N"}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow8" sourceRef="decideTLApprove" targetRef="submitForm">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${tlApprove == "n" || tlApprove == "N"}]]></conditionExpression>
</sequenceFlow>
<exclusiveGateway gatewayDirection="Unspecified" id="decideHRApprove" name="人事审批校验"/>
<sequenceFlow id="flow9" sourceRef="hr_approve" targetRef="decideHRApprove"/>
<endEvent id="endEvent" name="结束"/>
<sequenceFlow id="flow10" sourceRef="decideHRApprove" targetRef="endEvent">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${hrApprove == "y" || hrApprove == "Y"}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow11" sourceRef="decideHRApprove" targetRef="submitForm">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${hrApprove == "n" || hrApprove == "N"}]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
<bpmndi:BPMNPlane bpmnElement="second_approve">
<bpmndi:BPMNShape bpmnElement="startEvent" id="Shape-startEvent">
<omgdc:Bounds height="32.0" width="32.0" x="-17.5" y="-17.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="submitForm" id="Shape-submitForm">
<omgdc:Bounds height="55.0" width="105.0" x="-52.5" y="-27.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="105.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="decideSubmit" id="Shape-decideSubmit" isMarkerVisible="false">
<omgdc:Bounds height="32.0" width="32.0" x="-20.0" y="-20.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="tl_approve" id="Shape-tl_approve">
<omgdc:Bounds height="55.0" width="105.0" x="-52.5" y="-27.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="105.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="decideTLApprove" id="Shape-decideTLApprove" isMarkerVisible="false">
<omgdc:Bounds height="32.0" width="32.0" x="-20.0" y="-20.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="hr_approve" id="Shape-hr_approve">
<omgdc:Bounds height="55.0" width="105.0" x="-52.5" y="-27.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="105.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endEventCancel" id="Shape-endEventCancel">
<omgdc:Bounds height="32.0" width="32.0" x="-17.5" y="-17.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="decideHRApprove" id="Shape-decideHRApprove" isMarkerVisible="false">
<omgdc:Bounds height="32.0" width="32.0" x="-20.0" y="-20.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endEvent" id="Shape-endEvent">
<omgdc:Bounds height="32.0" width="32.0" x="-17.5" y="-17.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1" sourceElement="startEvent" targetElement="submitForm">
<omgdi:waypoint x="14.992185591719476" y="-1.5"/>
<omgdi:waypoint x="-1.5" y="-27.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2" sourceElement="submitForm" targetElement="decideSubmit">
<omgdi:waypoint x="-4.0" y="-27.0"/>
<omgdi:waypoint x="-4.0" y="12.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3" sourceElement="decideSubmit" targetElement="tl_approve">
<omgdi:waypoint x="-4.0" y="12.0"/>
<omgdi:waypoint x="-4.0" y="-27.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4" sourceElement="tl_approve" targetElement="decideTLApprove">
<omgdi:waypoint x="-4.0" y="-27.0"/>
<omgdi:waypoint x="-4.0" y="12.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5" sourceElement="decideTLApprove" targetElement="hr_approve">
<omgdi:waypoint x="-4.0" y="12.0"/>
<omgdi:waypoint x="-4.0" y="-27.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7" sourceElement="decideSubmit" targetElement="endEventCancel">
<omgdi:waypoint x="12.0" y="-4.0"/>
<omgdi:waypoint x="480.0" y="427.0"/>
<omgdi:waypoint x="14.992185591719476" y="-1.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10" sourceElement="decideHRApprove" targetElement="endEvent">
<omgdi:waypoint x="-4.0" y="-4.0"/>
<omgdi:waypoint x="14.904008928568928" y="-2.75"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8" sourceElement="decideTLApprove" targetElement="submitForm">
<omgdi:waypoint x="12.0" y="-4.0"/>
<omgdi:waypoint x="714.0" y="466.0"/>
<omgdi:waypoint x="362.0" y="466.0"/>
<omgdi:waypoint x="53.0" y="0.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11" sourceElement="decideHRApprove" targetElement="submitForm">
<omgdi:waypoint x="12.0" y="-4.0"/>
<omgdi:waypoint x="997.0" y="290.0"/>
<omgdi:waypoint x="410.0" y="290.0"/>
<omgdi:waypoint x="53.0" y="0.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9" sourceElement="hr_approve" targetElement="decideHRApprove">
<omgdi:waypoint x="-4.0" y="-27.0"/>
<omgdi:waypoint x="-4.0" y="12.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
程序实现
这里使用main方法+命令行交互的方法来实现流程流转,main方法中的内容如下:
logger.info("启动程序");
// 创建流程引擎
ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
ProcessEngine processEngine = cfg.buildProcessEngine();
String name = processEngine.getName();
String version = ProcessEngine.VERSION;
logger.info("流程引擎名称:{},版本:{}",name,version);
// 部署流程定义文件
RepositoryService repositoryService = processEngine.getRepositoryService();
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
deploymentBuilder.addClasspathResource("second_approve.bpmn20.xml");
Deployment deployment = deploymentBuilder.deploy();
String deploymentId = deployment.getId();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().
deploymentId(deploymentId).singleResult();
logger.info("流程文件:{},流程定义id:{}",processDefinition.getName(),processDefinition.getId());
// 启动流程
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
logger.info("流程实例id为:{}",processInstance.getId());
// 处理任务
Scanner scanner = new Scanner(System.in);
while (processInstance != null && !processInstance.isEnded()){
TaskService taskService = processEngine.getTaskService();
List<Task> taskList = taskService.createTaskQuery().list();
for(Task task : taskList){
logger.info("待处理任务:{}",task.getName());
FormService formService = processEngine.getFormService();
TaskFormData taskFormData = formService.getTaskFormData(task.getId());
List<FormProperty> formPropertyList = taskFormData.getFormProperties();
Map<String,Object> variables = new HashMap<String,Object>();
for(FormProperty formProperty : formPropertyList){
String line = null;
if(StringFormType.class.isInstance(formProperty.getType())){
logger.info("请输入{}:",formProperty.getName());
line = scanner.nextLine();
variables.put(formProperty.getId(),line);
} else if(DateFormType.class.isInstance(formProperty.getType())){
logger.info("请输入{}:(格式:yyyy-MM-dd)",formProperty.getName());
line = scanner.nextLine();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
try {
date = dateFormat.parse(line);
} catch (ParseException e) {
e.printStackTrace();
}
variables.put(formProperty.getId(),date);
}
logger.info("您输入的内容是:{}",line);
}
taskService.complete(task.getId(),variables);
}
logger.info("待处理任务数量有{}个",taskList.size());
}
logger.info("结束程序");
上述首先创建流程引擎配置类,接着使用配置类创建流程引擎,然后使用流程引擎获得各个service,通过这些service来实现流程部署,创建流程实例,执行每个节点的任务直到流程结束。