pom 文件添加jar
<!--jwt token-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.activiti/activiti-spring -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>6.0.0</version>
</dependency>
写好配置类
import org.activiti.engine.*;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.io.IOException;
/**
* @author wangsx
* @date Created in 09-10-2018
* @description
*/
@Configuration
public class ActivitiConfig {
@Bean
public ProcessEngine processEngine(DataSourceTransactionManager transactionManager, DataSource dataSource) throws IOException {
SpringProcessEngineConfiguration configuration = new SpringProcessEngineConfiguration();
//自动部署已有的流程文件
Resource[] resources = new PathMatchingResourcePatternResolver().getResources(ResourceLoader.CLASSPATH_URL_PREFIX + "processes/*.bpmn");
configuration.setTransactionManager(transactionManager);
configuration.setDataSource(dataSource);
configuration.setDatabaseSchemaUpdate("true");
configuration.setDeploymentResources(resources);
configuration.setDbIdentityUsed(false);
return configuration.buildProcessEngine();
}
@Bean
public RepositoryService repositoryService(ProcessEngine processEngine) {
return processEngine.getRepositoryService();
}
@Bean
public RuntimeService runtimeService(ProcessEngine processEngine) {
return processEngine.getRuntimeService();
}
@Bean
public TaskService taskService(ProcessEngine processEngine) {
return processEngine.getTaskService();
}
@Bean
public HistoryService historyService(ProcessEngine processEngine) {
return processEngine.getHistoryService();
}
@Bean
public ManagementService managementService(ProcessEngine processEngine) {
return processEngine.getManagementService();
}
@Bean
public IdentityService identityService(ProcessEngine processEngine) {
return processEngine.getIdentityService();
}
@Bean
public FormService formService(ProcessEngine processEngine){
return processEngine.getFormService();
}
}
springboot 在启动项目时会自动配置
测试的流程图
<?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="act_demo_audit">
<process id="act_demo_audit" name="act_demo_audit" isExecutable="true">
<startEvent id="Start" name="开始" activiti:formKey="demo/form"></startEvent>
<userTask id="firstLevelAudit" name="一级审批" activiti:candidateUsers="${firstLevel}"></userTask>
<userTask id="secondLevelAudit" name="二级审批" activiti:candidateUsers="${secondLevel}"></userTask>
<endEvent id="refuse" name="成功"></endEvent>
<sequenceFlow id="flow1" sourceRef="Start" targetRef="firstLevelAudit"></sequenceFlow>
<serviceTask id="acceptService" name="通过时业务处理" activiti:class="com.siemens.pms.act.service.impl.DemoAuditProcessor"></serviceTask>
<sequenceFlow id="flow4" sourceRef="secondLevelAudit" targetRef="refuseService">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${secondLevelPass}]]></conditionExpression>
</sequenceFlow>
<serviceTask id="refuseService" name="不通过时业务处理" activiti:class="com.siemens.pms.act.service.impl.DemoAuditProcessor"></serviceTask>
<sequenceFlow id="flow6" name="不通过" sourceRef="secondLevelAudit" targetRef="refuseService">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${!secondLevelPass}]]></conditionExpression>
</sequenceFlow>
<endEvent id="accept" name="失败"></endEvent>
<sequenceFlow id="flow8" sourceRef="refuseService" targetRef="accept"></sequenceFlow>
<sequenceFlow id="flow9" name="不通过" sourceRef="firstLevelAudit" targetRef="refuseService">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${!firstLevelPass}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow10" name="通过" sourceRef="secondLevelAudit" targetRef="acceptService">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${secondLevelPass}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow11" sourceRef="acceptService" targetRef="refuse"></sequenceFlow>
<exclusiveGateway id="exclusivegateway1" name="是否二级"></exclusiveGateway>
<sequenceFlow id="flow14" name="是" sourceRef="exclusivegateway1" targetRef="secondLevelAudit">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${secondLevel!=null}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow15" name="否" sourceRef="exclusivegateway1" targetRef="acceptService">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${secondLevel==null}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow16" name="通过" sourceRef="firstLevelAudit" targetRef="exclusivegateway1">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${firstLevelPass}]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_act_demo_audit">
<bpmndi:BPMNPlane bpmnElement="act_demo_audit" id="BPMNPlane_act_demo_audit">
<bpmndi:BPMNShape bpmnElement="Start" id="BPMNShape_Start">
<omgdc:Bounds height="51.0" width="71.0" x="30.0" y="165.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="firstLevelAudit" id="BPMNShape_firstLevelAudit">
<omgdc:Bounds height="61.0" width="161.0" x="140.0" y="160.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="secondLevelAudit" id="BPMNShape_secondLevelAudit">
<omgdc:Bounds height="61.0" width="181.0" x="480.0" y="160.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="refuse" id="BPMNShape_refuse">
<omgdc:Bounds height="51.0" width="71.0" x="1020.0" y="165.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="acceptService" id="BPMNShape_acceptService">
<omgdc:Bounds height="81.0" width="151.0" x="780.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="refuseService" id="BPMNShape_refuseService">
<omgdc:Bounds height="61.0" width="181.0" x="480.0" y="290.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="accept" id="BPMNShape_accept">
<omgdc:Bounds height="41.0" width="61.0" x="540.0" y="430.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">
<omgdc:Bounds height="40.0" width="40.0" x="360.0" y="170.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="101.0" y="190.0"></omgdi:waypoint>
<omgdi:waypoint x="140.0" y="190.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="570.0" y="221.0"></omgdi:waypoint>
<omgdi:waypoint x="570.0" y="290.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
<omgdi:waypoint x="570.0" y="221.0"></omgdi:waypoint>
<omgdi:waypoint x="570.0" y="290.0"></omgdi:waypoint>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="16.0" width="48.0" x="570.0" y="221.0"></omgdc:Bounds>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
<omgdi:waypoint x="570.0" y="351.0"></omgdi:waypoint>
<omgdi:waypoint x="570.0" y="430.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
<omgdi:waypoint x="220.0" y="221.0"></omgdi:waypoint>
<omgdi:waypoint x="220.0" y="320.0"></omgdi:waypoint>
<omgdi:waypoint x="480.0" y="320.0"></omgdi:waypoint>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="16.0" width="48.0" x="220.0" y="221.0"></omgdc:Bounds>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10">
<omgdi:waypoint x="661.0" y="190.0"></omgdi:waypoint>
<omgdi:waypoint x="780.0" y="190.0"></omgdi:waypoint>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="16.0" width="32.0" x="661.0" y="190.0"></omgdc:Bounds>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11">
<omgdi:waypoint x="931.0" y="190.0"></omgdi:waypoint>
<omgdi:waypoint x="1020.0" y="190.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow14" id="BPMNEdge_flow14">
<omgdi:waypoint x="400.0" y="190.0"></omgdi:waypoint>
<omgdi:waypoint x="480.0" y="190.0"></omgdi:waypoint>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="16.0" width="16.0" x="400.0" y="190.0"></omgdc:Bounds>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow15" id="BPMNEdge_flow15">
<omgdi:waypoint x="380.0" y="170.0"></omgdi:waypoint>
<omgdi:waypoint x="380.0" y="88.0"></omgdi:waypoint>
<omgdi:waypoint x="578.0" y="88.0"></omgdi:waypoint>
<omgdi:waypoint x="855.0" y="88.0"></omgdi:waypoint>
<omgdi:waypoint x="855.0" y="150.0"></omgdi:waypoint>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="16.0" width="16.0" x="380.0" y="170.0"></omgdc:Bounds>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow16" id="BPMNEdge_flow16">
<omgdi:waypoint x="301.0" y="190.0"></omgdi:waypoint>
<omgdi:waypoint x="360.0" y="190.0"></omgdi:waypoint>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="16.0" width="32.0" x="301.0" y="190.0"></omgdc:Bounds>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
核心API
ProcessEngine
说明:
- 在Activiti中最核心的类,其他的类都是由他而来。
- 产生方式:
在前面看到了两种创建ProcessEngine(流程引擎)的方式,而这里要简化很多,调用ProcessEngines的getDefaultProceeEngine方法时会自动加载classpath下名为activiti.cfg.xml文件。
- 可以产生RepositoryService
- 可以产生RuntimeService
- 可以产生TaskService
各个Service的作用:
RepositoryService | 管理流程定义 |
RuntimeService | 执行管理,包括启动、推进、删除流程实例等操作 |
TaskService | 任务管理 |
HistoryService | 历史管理(执行完的数据的管理) |
IdentityService | 组织机构管理 |
FormService | 一个可选服务,任务表单管理 |
ManagerService |
|
RepositoryService
是Activiti的仓库服务类。所谓的仓库指流程定义文档的两个文件:bpmn文件和流程图片。
- 产生方式
- 可以产生DeploymentBuilder,用来定义流程部署的相关参数
- 删除流程定义
RuntimeService
是activiti的流程执行服务类。可以从这个服务类中获取很多关于流程执行相关的信息。
TaskService
是activiti的任务服务类。可以从这个类中获取任务的信息。
HistoryService
是activiti的查询历史信息的类。在一个流程执行完成后,这个对象为我们提供查询历史信息。
ProcessDefinition
流程定义类。可以从这里获得资源文件等。
ProcessInstance
代表流程定义的执行实例。如范冰冰请了一天的假,她就必须发出一个流程实例的申请。一个流程实例包括了所有的运行节点。我们可以利用这个对象来了解当前流程实例的进度等信息。流程实例就表示一个流程从开始到结束的最大的流程分支,即一个流程中流程实例只有一个。
Execution
Activiti用这个对象去描述流程执行的每一个节点。在没有并发的情况下,Execution就是同ProcessInstance。流程按照流程定义的规则执行一次的过程,就可以表示执行对象Execution。
如图为ProcessInstance的源代码:
从源代码中可以看出ProcessInstance就是Execution。但在现实意义上有所区别:
在单线流程中,如上图的贷款流程,ProcessInstance与Execution是一致的。
这个例子有一个特点:wire money(汇钱)和archive(存档)是并发执行的。 这个时候,总线路代表ProcessInstance,而分线路中每个活动代表Execution。
总结:
* 一个流程中,执行对象可以存在多个,但是流程实例只能有一个。
* 当流程按照规则只执行一次的时候,那么流程实例就是执行对象。