activiti入门

时间:2021-05-16 06:24:27

一、Activiti简介

  Activiti 是一个针对商务人士、 开发人员和系统管理员的轻量级的工作流和业务流程管理 (BPM) 平台。它的核心是Java的高速和可靠的 BPMN 2 流程引擎。它是开源的、并且提供宽松的Apache许可。Activiti可以在任何Java应用中运行,可以运行在在服务器、集群或云环境。它可以与Spring进行整合,它非常轻便和机遇简单的概念。Activiti是由原来开发JBPM的作者所建立的,所以Activiti与JBPM早期的版本(JBPM4,BPM4之后版本已完全抛弃JBPM4的基础代码,转而基于Drools Flow构建)比较相似,适合于早期的JBPM用户使用。

   Activiti 下载地址为:http://activiti.org/download.html。这里使用的是activiti-5.18.0.zip 版本。

二、eclipse 流程设计器

  使用Activiti需要设计流程,然后再进行部署,运行、流转。这里使用Activiti提供的eclipse插件进行流程设计。以下为插件的安装:

  1、点击eclipse Help -》 Install New Software. 并在界面点击Add输入如下内容,并点击OK按钮。如下图所示

  activiti入门

  2、点击Select All并点击Next,按照界面的提示直到出现如下界面

  activiti入门

  点击Finish,等待安装,安装完成重启eclipse即可。

三、Activiti 数据库配置

  activiti-5.17.0.zip下载完成后,解压。将libs下的activiti-engine-5.17.0.jar文件解压。创建数据的脚步就在org\activiti\db\create目录下。 该目录下有多种版本的数据库脚本。

  • engine:为引擎运行所必须的表。
  • identity: 为包含用户,用户组和用户组里的成员。这些表是可选的,但是当引擎是使用默认的身份标识管理进行装载的时候,这些表必须存在。
  • history:这些表包含一些历史和审计信息。当history level 设置成none的时候是可选的,但是这样会使一些存储在history数据库里面的新特性失效(如任务里面的说明)。

  注意:对于mysql来说,版本低于 5.6.4的mysql不支持 带有毫秒精确度的timestamp和date 类型。所以低于 5.6.4版本的mysql需要执行如下脚本文件:

activiti.mysql55.create.engine.sql
activiti.mysql.create.identity.sql
activiti.mysql55.create.history.sql

  而版本号在5.6.4以及以上的mysql需要执行如下脚本

activiti.mysql.create.engine.sql
activiti.mysql.create.identity.sql
activiti.mysql.create.history.sql

  创建完成后,生成的表入下图所示:

  activiti入门

四、示例

  1、设计流程定义

    选择新建一个Activiti Diagram 命名为test,在拖动Palette中的组件到右边的设计区域。本例子使用到的有StartEvent、UserTask、EndEvent并使用SequenceFlow将它们连接起来,如下图所示:

  activiti入门    

  流程定义文件test.bpmn内容如下图所示:

 <?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="test" name="My process" isExecutable="true">
<startEvent id="start" name="Start"></startEvent>
<endEvent id="end" name="End"></endEvent>
<userTask id="usertask1" name="step1" activiti:assignee="kermit"></userTask>
<userTask id="usertask2" name="step2" activiti:candidateUsers="kermit,gonzo"></userTask>
<userTask id="usertask3" name="step3" activiti:candidateGroups="management,accountancy"></userTask>
<sequenceFlow id="flow1" sourceRef="start" targetRef="usertask1"></sequenceFlow>
<sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
<sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>
<sequenceFlow id="flow4" sourceRef="usertask3" targetRef="end"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_test">
<bpmndi:BPMNPlane bpmnElement="test" id="BPMNPlane_test">
<bpmndi:BPMNShape bpmnElement="start" id="BPMNShape_start">
<omgdc:Bounds height="35.0" width="35.0" x="20.0" y="129.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="end" id="BPMNShape_end">
<omgdc:Bounds height="35.0" width="35.0" x="610.0" y="129.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="110.0" y="119.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
<omgdc:Bounds height="55.0" width="105.0" x="290.0" y="119.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
<omgdc:Bounds height="55.0" width="105.0" x="450.0" y="119.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="55.0" y="146.0"></omgdi:waypoint>
<omgdi:waypoint x="110.0" y="146.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="215.0" y="146.0"></omgdi:waypoint>
<omgdi:waypoint x="290.0" y="146.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="395.0" y="146.0"></omgdi:waypoint>
<omgdi:waypoint x="450.0" y="146.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="555.0" y="146.0"></omgdi:waypoint>
<omgdi:waypoint x="610.0" y="146.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>

  2、代码示例

  工程使用maven构建,pom.xml文件内容如下:

 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.shh</groupId>
<artifactId>activitytest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>activitytest</name>
<url>http://maven.apache.org</url> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<activiti-version>5.18.0</activiti-version>
</properties>
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>${activiti-version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>${activiti-version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.2.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>
</dependencies>
</project>

  spring配置文件activiti.cfg.xml内容如下:

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="processEngineConfiguration"
class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="databaseSchemaUpdate" value="true" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=utf8" />
<property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
<property name="jdbcUsername" value="root" />
<property name="jdbcPassword" value="" />
<property name="jobExecutorActivate" value="true" />
</bean>
</beans>

  测试类TestActiviti代码如下:

 package com.shh.test;

 import java.util.List;

 import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.task.Task;
import org.junit.Before;
import org.junit.Test; /**
* 测试流程
* @author 20150205
*
*/
public class TestActiviti {
ProcessEngine processEngine = null;
RepositoryService repositoryService = null;
RuntimeService runtimeService = null;
TaskService taskService = null; @Before
public void init() {
//加载spring配置文件,创建 ProcessEngine
processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml")
.buildProcessEngine();
repositoryService = processEngine.getRepositoryService();
runtimeService = processEngine.getRuntimeService();
taskService = processEngine.getTaskService();
} /**
* 部署流程定义加载test.bpmn文件
*/
@Test
public void deploy(){
Deployment deployment = repositoryService.createDeployment().addClasspathResource("diagrams/test.bpmn").deploy();
String id = deployment.getId();
System.out.println("***************部署流程定义完成***************" + id);
} /**
* 启动一个请假流程
*/
@Test
public void start() {
for(int i = 0 ; i < 5; i++){
String processId = runtimeService.startProcessInstanceByKey("test").getId();
System.out.println("***************启动第" + i + "个请假流程完成***************" + processId);
}
} /**
* 第一步
*/
@Test
public void step1(){
System.out.println("***************step1流程开始***************");
List<Task> tasks = taskService.createTaskQuery().taskAssignee("kermit").list();//kermit的任务
List<Task> tasks2 = taskService.createTaskQuery().taskAssignee("gonzo").list();//gonzo的任务
System.out.println(tasks.size());
System.out.println(tasks2.size());//指定了kermit,所以gonzo的任务数量为0 for (Task task : tasks) {
System.out.println("kermit的任务taskname:" + task.getName() + ",id:" + task.getId());//任务的name与id
System.out.println(task.getAssignee());//任务拥有者
System.out.println(task.getProcessInstanceId());//流程实例id
System.out.println(task.getProcessDefinitionId());//流程定义id
taskService.complete(task.getId());//完成任务
} System.out.println("kermit的任务数量:" + taskService.createTaskQuery().taskAssignee("kermit").count());
System.out.println("***************step1流程结束***************");
} /**
* 第二步
*/
@Test
public void step2(){
System.out.println("***************step2流程开始***************");
List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit").list();//kermit可领取的任务
List<Task> tasks2 = taskService.createTaskQuery().taskCandidateUser("gonzo").list();//gonzo可领取的任务
System.out.println(tasks.size());
System.out.println(tasks2.size()); for (int i = 0 ; i < tasks.size(); i++) {
Task task = tasks.get(i);
System.out.println("任务taskname:" + task.getName() + ",id:" + task.getId());//任务的name与id
if(i % 2 == 0){
taskService.claim(task.getId(), "kermit");//kermit领取任务
}else{
taskService.claim(task.getId(), "gonzo");//gonzo领取任务
}
} tasks = taskService.createTaskQuery().taskAssignee("kermit").list();
tasks2 = taskService.createTaskQuery().taskAssignee("gonzo").list();
System.out.println("kermit的任务数量:" + tasks.size());
System.out.println("gonzo的任务数量:" + tasks2.size()); for(Task t : tasks){
taskService.complete(t.getId());//完成任务
}
for(Task t : tasks2){
taskService.complete(t.getId());//完成任务
}
tasks = taskService.createTaskQuery().taskAssignee("kermit").list();
tasks2 = taskService.createTaskQuery().taskAssignee("gonzo").list();
System.out.println("kermit的任务数量:" + tasks.size());
System.out.println("gonzo的任务数量:" + tasks2.size());
System.out.println("***************step2流程结束***************");
} @Test
public void step3(){
System.out.println("***************step3流程开始***************");
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();//management组可领取的任务
List<Task> tasks2 = taskService.createTaskQuery().taskCandidateGroup("accountancy").list();//accountancy组可领取的任务
System.out.println(tasks.size());
System.out.println(tasks2.size()); for (int i = 0 ; i < tasks.size(); i++) {
Task task = tasks.get(i);
System.out.println("任务taskname:" + task.getName() + ",id:" + task.getId());//任务的name与id
if(i % 2 == 0){
taskService.claim(task.getId(), "kermit");
}else{
taskService.claim(task.getId(), "gonzo");
}
}
tasks = taskService.createTaskQuery().taskAssignee("kermit").list();
tasks2 = taskService.createTaskQuery().taskAssignee("gonzo").list();
System.out.println("kermit的任务数量:" + tasks.size());
System.out.println("gonzo的任务数量:" + tasks2.size()); for(Task t : tasks){
taskService.complete(t.getId());//完成任务
}
for(Task t : tasks2){
taskService.complete(t.getId());//完成任务
}
tasks = taskService.createTaskQuery().taskAssignee("kermit").list();
tasks2 = taskService.createTaskQuery().taskAssignee("gonzo").list();
System.out.println("kermit的任务数量:" + tasks.size());
System.out.println("gonzo的任务数量:" + tasks2.size()); System.out.println("***************step3流程结束***************");
}
}

  依次执行deploy();、start();、step1();、step2();、step3()方法,结果如下:

八月 04, 2015 10:48:41 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [activiti.cfg.xml]
八月 04, 2015 10:48:44 上午 org.activiti.engine.impl.ProcessEngineImpl <init>
信息: ProcessEngine default created
八月 04, 2015 10:48:44 上午 org.activiti.engine.impl.bpmn.deployer.BpmnDeployer deploy
信息: Processing resource diagrams/test.bpmn
***************部署流程定义完成***************60001
***************启动第0个请假流程完成***************60005
***************启动第1个请假流程完成***************60010
***************启动第2个请假流程完成***************60015
***************启动第3个请假流程完成***************60020
***************启动第4个请假流程完成***************60025
***************step1流程开始***************
5
0
kermit的任务taskname:step1,id:60008
kermit
60005
test:5:60004
kermit的任务taskname:step1,id:60013
kermit
60010
test:5:60004
kermit的任务taskname:step1,id:60018
kermit
60015
test:5:60004
kermit的任务taskname:step1,id:60023
kermit
60020
test:5:60004
kermit的任务taskname:step1,id:60028
kermit
60025
test:5:60004
kermit的任务数量:0
***************step1流程结束***************
***************step2流程开始***************
5
5
任务taskname:step2,id:60031
任务taskname:step2,id:60036
任务taskname:step2,id:60041
任务taskname:step2,id:60046
任务taskname:step2,id:60051
kermit的任务数量:3
gonzo的任务数量:2
kermit的任务数量:0
gonzo的任务数量:0
***************step2流程结束***************
***************step3流程开始***************
5
5
任务taskname:step3,id:60056
任务taskname:step3,id:60060
任务taskname:step3,id:60064
任务taskname:step3,id:60068
任务taskname:step3,id:60072
kermit的任务数量:3
gonzo的任务数量:2
kermit的任务数量:0
gonzo的任务数量:0
***************step3流程结束***************