理解了工作流的大概过程可以尝试编辑一个工作流页面bpmn文件,然后可以对其进行基本的使用,理解代码对工作流的处理流程。
文件修改为.xml文件后可由后端读取解析,其解析的内容为:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 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" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="second_approve" name="二级审批流程" isExecutable="true">
<startEvent id="startEvent" name="开始"></startEvent>
<userTask id="submitForm" name="填写审批信息">
<extensionElements>
<activiti:formProperty id="message" name="申请信息" type="string" required="true"></activiti:formProperty>
<activiti:formProperty id="name" name="申请人名称" type="string" required="true"></activiti:formProperty>
<activiti:formProperty id="submitTime" name="提交时间" type="date" datePattern="yyyy-MM-dd" required="true"></activiti:formProperty>
<activiti:formProperty id="submitType" name="确认申请" type="string" required="true"></activiti:formProperty>
</extensionElements>
</userTask>
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="submitForm"></sequenceFlow>
<exclusiveGateway id="decideSubmit" name="提交或取消"></exclusiveGateway>
<sequenceFlow id="flow2" sourceRef="submitForm" targetRef="decideSubmit"></sequenceFlow>
<userTask id="tl_approve" name="主管审批">
<extensionElements>
<activiti:formProperty id="tlApprove" name="主管审批结果" type="string" required="true"></activiti:formProperty>
<activiti:formProperty id="tlMessage" name="主管审批备注" type="string" required="true"></activiti:formProperty>
</extensionElements>
</userTask>
<sequenceFlow id="flow3" sourceRef="decideSubmit" targetRef="tl_approve">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${ submitType == "y" || submitType == "Y" }]]></conditionExpression>
</sequenceFlow>
<exclusiveGateway id="decideTLApprove" name="主管审批校验"></exclusiveGateway>
<sequenceFlow id="flow4" sourceRef="tl_approve" targetRef="decideTLApprove"></sequenceFlow>
<userTask id="hr_approve" name="人事审批">
<extensionElements>
<activiti:formProperty id="hrApprove" name="人事审批结果" type="string" required="true"></activiti:formProperty>
<activiti:formProperty id="hrMessage" name="人事审批备注" type="string" required="true"></activiti:formProperty>
</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="取消"></endEvent>
<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 id="decideHRApprove" name="人事审批校验"></exclusiveGateway>
<sequenceFlow id="flow9" sourceRef="hr_approve" targetRef="decideHRApprove"></sequenceFlow>
<endEvent id="endEvent" name="结束"></endEvent>
<sequenceFlow id="flow10" sourceRef="decideHRApprove" targetRef="endEvent">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${ tlApprove == "y" || tlApprove == "Y" }]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow11" sourceRef="decideHRApprove" targetRef="submitForm">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${ hrApprove == "n" || hrApprove == "N" }]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_second_approve">
<bpmndi:BPMNPlane bpmnElement="second_approve" id="BPMNPlane_second_approve">
<bpmndi:BPMNShape bpmnElement="startEvent" id="BPMNShape_startEvent">
<omgdc:Bounds height="35.0" width="35.0" x="150.0" y="290.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="submitForm" id="BPMNShape_submitForm">
<omgdc:Bounds height="55.0" width="105.0" x="230.0" y="280.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="decideSubmit" id="BPMNShape_decideSubmit">
<omgdc:Bounds height="40.0" width="40.0" x="380.0" y="288.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="tl_approve" id="BPMNShape_tl_approve">
<omgdc:Bounds height="55.0" width="105.0" x="465.0" y="281.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="decideTLApprove" id="BPMNShape_decideTLApprove">
<omgdc:Bounds height="40.0" width="40.0" x="614.0" y="288.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="hr_approve" id="BPMNShape_hr_approve">
<omgdc:Bounds height="55.0" width="105.0" x="701.0" y="280.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endEventCancel" id="BPMNShape_endEventCancel">
<omgdc:Bounds height="35.0" width="35.0" x="500.0" y="390.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="decideHRApprove" id="BPMNShape_decideHRApprove">
<omgdc:Bounds height="40.0" width="40.0" x="869.0" y="287.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endEvent" id="BPMNShape_endEvent">
<omgdc:Bounds height="35.0" width="35.0" x="960.0" y="290.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="185.0" y="307.0"></omgdi:waypoint>
<omgdi:waypoint x="230.0" y="307.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="335.0" y="307.0"></omgdi:waypoint>
<omgdi:waypoint x="380.0" y="308.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="420.0" y="308.0"></omgdi:waypoint>
<omgdi:waypoint x="465.0" y="308.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="570.0" y="308.0"></omgdi:waypoint>
<omgdi:waypoint x="614.0" y="308.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
<omgdi:waypoint x="654.0" y="308.0"></omgdi:waypoint>
<omgdi:waypoint x="701.0" y="307.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
<omgdi:waypoint x="400.0" y="328.0"></omgdi:waypoint>
<omgdi:waypoint x="400.0" y="407.0"></omgdi:waypoint>
<omgdi:waypoint x="500.0" y="407.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
<omgdi:waypoint x="634.0" y="288.0"></omgdi:waypoint>
<omgdi:waypoint x="634.0" y="241.0"></omgdi:waypoint>
<omgdi:waypoint x="282.0" y="241.0"></omgdi:waypoint>
<omgdi:waypoint x="282.0" y="280.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
<omgdi:waypoint x="806.0" y="307.0"></omgdi:waypoint>
<omgdi:waypoint x="869.0" y="307.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10">
<omgdi:waypoint x="909.0" y="307.0"></omgdi:waypoint>
<omgdi:waypoint x="960.0" y="307.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11">
<omgdi:waypoint x="889.0" y="287.0"></omgdi:waypoint>
<omgdi:waypoint x="889.0" y="196.0"></omgdi:waypoint>
<omgdi:waypoint x="282.0" y="196.0"></omgdi:waypoint>
<omgdi:waypoint x="282.0" y="280.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
用代码对流程进行开发使用。
package com.gjp.activiti.helloworld;
import com.google.common.collect.Maps;
import com.sun.org.apache.xpath.internal.operations.Or;
import org.activiti.engine.*;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.impl.form.DateFormType;
import org.activiti.engine.impl.form.StringFormType;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
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 java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class DemoActiviti {
private static final Logger logger = LoggerFactory.getLogger(DemoActiviti.class);
public static void main(String[] args) throws ParseException {
System.out.println("我启动了!");
//创建流程引擎
ProcessEngine processEngine = getProcessEngine();
//部署流程定义文件
ProcessDefinition processDefinition = getDeploymentBuilder(processEngine);
//启动流程
ProcessInstance processInstance = getProcessInstance(processEngine, processDefinition);
//处理流程任务
processInstanceDuelWith(processInstance, processEngine);
System.out.println("我结束了!");
}
/**
* 创建流程引擎
* @return
*/
private static ProcessEngine getProcessEngine(){
ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
ProcessEngine processEngine = cfg.buildProcessEngine();
String name = processEngine.getName();
String version = ProcessEngine.VERSION;
// logger.info("我的引擎名称为{},版本为{}",name,version);
System.out.println(String.format("流程引擎名称{ %s },版本{ %s }", name, version));
return processEngine;
}
/**
* 部署流程定义文件
* @param processEngine 获取创建的流程空间
* @return
*/
private static ProcessDefinition getDeploymentBuilder(ProcessEngine processEngine){
RepositoryService repositoryService = processEngine.getRepositoryService();
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
//deploymentBuilder.addClasspathResource("secound_approve.bpmn.xml");
Deployment deployment = deploymentBuilder.
addClasspathResource("secound_approve.bpmn.xml").deploy();;
String deploymentId = deployment.getId();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId(deploymentId)
.singleResult();//根据id获取流程定义对象
// logger.info("流程定义文件{},流程ID{}",processDefinition.getName(),processDefinition.getId());
System.out.println(String.format("流程定义文件{ %s },流程id{ %s }", processDefinition.getName(), processDefinition.getId()));
return processDefinition;
}
/**
* 启动流程
* @param processEngine 获取创建的流程空间
* @param processDefinition 获取部署的流程
* @return 返回启动的流程实例
*/
private static ProcessInstance getProcessInstance(ProcessEngine processEngine, ProcessDefinition processDefinition){
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
System.out.println(String.format("启动流程{%s}", processInstance.getProcessDefinitionKey()));
return processInstance;
}
/**
* 处理工作任务
* @param processInstance 获取流程实例
* @param processEngine 获取流程引擎模板
* @throws ParseException 日期转化时异常输出
*/
private static void processInstanceDuelWith(ProcessInstance processInstance, ProcessEngine processEngine ) throws ParseException {
Scanner scanner = new Scanner(System.in);
while (processInstance!=null && !processInstance.isEnded()) {
//当流程没有结束的时候,继续获取流程信息
TaskService taskService = processEngine.getTaskService();//获取工作流服务
List<Task> processEngineList = taskService.createTaskQuery().list();
System.out.println(String.format("任务总数为:{%s}", processEngineList.size()));
for (Task task : processEngineList) {
System.out.println(String.format("待处理的任务为:{%s}", task.getName()));
//初始化表单服务类并初始化工作流程数据
FormService formService = processEngine.getFormService();
TaskFormData taskFormData = formService.getTaskFormData(task.getId());
//获取bpmn文件中的表单内容
List<FormProperty> formPropertyList = taskFormData.getFormProperties();
for (FormProperty formProperty :formPropertyList){
System.out.println(String.format("流程id:%s ,流程值:%s", formProperty.getId(), formProperty.getValue()));
}
//这里的内容是不允许key为空
Map<String , Object> variables = new Hashtable<String, Object>();
//获取了流程表单内容进行处理
//根据表单的行类型,获取输入类型
for (FormProperty formProperty : formPropertyList ){
String inLine = "";
if ((StringFormType.class).isInstance(formProperty.getType())){
System.out.println(String.format("请输入%s:", formProperty.getName()));
inLine = scanner.nextLine();
variables.put( formProperty.getId() , inLine);
}else if ((DateFormType.class).isInstance(formProperty.getType())){
System.out.println(String.format("输入%s,格式为:yyyy-MM-dd:", formProperty.getName()));
inLine = scanner.nextLine();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(inLine);
variables.put(formProperty.getId(), date);
} else {
logger.info("其他类型不支持");
}
logger.info("你输入的内容为" + inLine);
}
//提交流程
taskService.complete( task.getId() , variables);
}
//获取流程实例最新状态
processInstance = processEngine.getRuntimeService()
.createProcessInstanceQuery()
.processInstanceId(processInstance.getId())
.singleResult();
}
}
}
其结果如下:
我启动了!
流程引擎名称{ default },版本{ 6.0.0.4 }
流程定义文件{ 二级审批流程 },流程id{ second_approve:1:4 }
启动流程{second_approve}
任务总数为:{1}
待处理的任务为:{填写审批信息}
流程id:message ,流程值:null
流程id:name ,流程值:null
流程id:submitTime ,流程值:null
流程id:submitType ,流程值:null
请输入申请信息:
---我想请假--
请输入申请人名称:
--小麦麸--
输入提交时间,格式为:yyyy-MM-dd:
2018-09-17
请输入确认申请:
y
任务总数为:{1}
待处理的任务为:{主管审批}
流程id:tlApprove ,流程值:null
流程id:tlMessage ,流程值:null
请输入主管审批结果:
y
请输入主管审批备注:
--2018-09-17 这个人的请假我不想给--
任务总数为:{1}
待处理的任务为:{人事审批}
流程id:hrApprove ,流程值:null
流程id:hrMessage ,流程值:null
请输入人事审批结果:
y
请输入人事审批备注:
--2018-09-11 这个人的请假我不想给--
我结束了!
Process finished with exit code 0