http://www.mossle.com/docs/activiti/
http://activiti.org/designer/archived/
http://blog.csdn.net/yangyi22/article/details/9225849
http://www.360doc.com/content/12/0629/10/10058718_221120921.shtml
http://www.activiti.org/community.html
1.环境要求和基本演示
(1)操作系统环境变量中要配置JAVA_HOME(2)将activiti-5.14.zip压缩文件中的 activiti-explorer.war 复制到tomcat中的webapps
(3)启动浏览器http://localhost:8080/activiti-exp lorer,以 kermit/kermit登录
演示版本中共有三个用户
UserId Password Security roles
kermit kermit admin
gonzo gonzo manager
fozzie fozzie user
(4)下载eclipse_indigo(eclipse3.7),解压缩运行,indigo版本集成了maven,插件Activiti BPMN 2.0 designer必须安装在indigo中
(5)运行eclipse,安装Activiti BPMN 2.0 designer插件,具体参见:http://www.ecmkit.com/zh-hans/2012/03/21/activiti-workflow-hell
Help -> Install New Software,输入以下站点信息:
Name: Activiti BPMN 2.0 designer
Location: http://activiti.org/designer/update/
2.数据库配置为oracle
(1)将database->create目录中对应的sql语句复制到数据库中执行即可
我的是oracle11g,结果出现了“A-01460: 转换请求无法实现或不合理”问题,将驱动转换成ojdbc6.jar,还要在环境变量classpath中配置一下
3.相关jar包
(1)在eclipse中新建一个Web Project
(2)将activiti-5.11中lib目录下所有jar包复制到web-inf\lib\
(3)复制activation-1.1.jar;commons-dbcp-1.4.jar;commons-email-1.2.jar;commons-lang3-3.1.jar;commons-logging.jar;commons-pool-1.5.4.jar;mail-1.4.1.jar
spring 3.1所有jar包,数据库jar包
(4)相关jar包如果没有,可以到这个去下http://yiyiboy2010.iteye.com/blog/1530924
4.演示代码
(1)新建一个bpmn
可以自己新建,也可以用http://yiyiboy2010.iteye.com/blog/1530924里的Interview.bpmn20.xml,将名字改成Interview.bpmn,放在根目录下
注意:从activti5.10开始,bpmn20.xml后缀都改成了bpmn,如果需要图片,自己从eclipse中导出
(2)在根目录下新建一个数据库配置文件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/webauth?useUnicode=true&characterEncoding=utf-8" />
<property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
<property name="jdbcUsername" value="root" />
<property name="jdbcPassword" value="" />
<property name="jobExecutorActivate" value="true" />
</bean>
<!--
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="databaseSchemaUpdate" value="true" />
<property name="jdbcUrl" value="jdbc:oracle:thin:@192.108.119.45:1521:test" />
<property name="jdbcDriver" value="oracle.jdbc.driver.OracleDriver" />
<property name="jdbcUsername" value="username" />
<property name="jdbcPassword" value="password" />
<property name="jobExecutorActivate" value="true" />
</bean>
-->
</beans>
(3)新建一个java测试类
import java.util.List;
import org.activiti.engine.HistoryService;
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.history.HistoricProcessInstance;
import org.activiti.engine.task.Task;
public class Test {
//本流程模拟的是某公司2012年实习生招聘流程
//张三来参加该招聘流程,公司相关负责人负责处理流程
public static void main(String[] args) {
//加载配置文件
ProcessEngine processEngine = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("activiti.cfg.xml")
.buildProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
RuntimeService runtimeService = processEngine.getRuntimeService();
repositoryService.createDeployment()
.addClasspathResource("Interview.bpmn")
.deploy();
String processId = runtimeService.startProcessInstanceByKey("Interview").getId();
TaskService taskService = processEngine.getTaskService();
HistoryService historyService = processEngine.getHistoryService();
//得到笔试的流程
System.out.println("***************笔试流程开始***************");
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("人力资源部").list();
for (Task task : tasks) {
System.out.println("人力资源部的任务:name:"+task.getName()+",id:"+task.getId());
taskService.claim(task.getId(), "张三");
}
System.out.println("张三的任务数量:"+taskService.createTaskQuery().taskAssignee("张三").count());
tasks = taskService.createTaskQuery().taskAssignee("张三").list();
for (Task task : tasks) {
System.out.println("张三的任务:name:"+task.getName()+",id:"+task.getId());
taskService.complete(task.getId());
}
System.out.println("张三的任务数量:"+taskService.createTaskQuery().taskAssignee("张三").count());
System.out.println("***************笔试流程结束***************");
System.out.println("***************一面流程开始***************");
tasks = taskService.createTaskQuery().taskCandidateGroup("技术部").list();
for (Task task : tasks) {
System.out.println("技术部的任务:name:"+task.getName()+",id:"+task.getId());
taskService.claim(task.getId(), "李四");
}
System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
for (Task task : tasks) {
System.out.println("李四的任务:name:"+task.getName()+",id:"+task.getId());
taskService.complete(task.getId());
}
System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
System.out.println("***************一面流程结束***************");
System.out.println("***************二面流程开始***************");
tasks = taskService.createTaskQuery().taskCandidateGroup("技术部").list();
for (Task task : tasks) {
System.out.println("技术部的任务:name:"+task.getName()+",id:"+task.getId());
taskService.claim(task.getId(), "李四");
}
System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
for (Task task : tasks) {
System.out.println("李四的任务:name:"+task.getName()+",id:"+task.getId());
taskService.complete(task.getId());
}
System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
System.out.println("***************二面流程结束***************");
System.out.println("***************HR面流程开始***************");
tasks = taskService.createTaskQuery().taskCandidateGroup("人力资源部").list();
for (Task task : tasks) {
System.out.println("技术部的任务:name:"+task.getName()+",id:"+task.getId());
taskService.claim(task.getId(), "李四");
}
System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
for (Task task : tasks) {
System.out.println("李四的任务:name:"+task.getName()+",id:"+task.getId());
taskService.complete(task.getId());
}
System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
System.out.println("***************HR面流程结束***************");
System.out.println("***************录用流程开始***************");
tasks = taskService.createTaskQuery().taskCandidateGroup("人力资源部").list();
for (Task task : tasks) {
System.out.println("技术部的任务:name:"+task.getName()+",id:"+task.getId());
taskService.claim(task.getId(), "李四");
}
System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
for (Task task : tasks) {
System.out.println("李四的任务:name:"+task.getName()+",id:"+task.getId());
taskService.complete(task.getId());
}
System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
System.out.println("***************录用流程结束***************");
HistoricProcessInstance historicProcessInstance = historyService
.createHistoricProcessInstanceQuery()
.processInstanceId(processId).singleResult();
System.out.println("流程结束时间:"+historicProcessInstance.getEndTime());
System.exit(0);
}
}
运行结果为
***************笔试流程开始***************
人力资源部的任务:name:笔试,id:8
张三的任务数量:1
张三的任务:name:笔试,id:8
张三的任务数量:0
***************笔试流程结束***************
***************一面流程开始***************
技术部的任务:name:技术一面,id:11
李四的任务数量:1
李四的任务:name:技术一面,id:11
李四的任务数量:0
***************一面流程结束***************
***************二面流程开始***************
技术部的任务:name:技术二面,id:14
李四的任务数量:1
李四的任务:name:技术二面,id:14
李四的任务数量:0
***************二面流程结束***************
***************HR面流程开始***************
技术部的任务:name:HR面,id:17
李四的任务数量:1
李四的任务:name:HR面,id:17
李四的任务数量:0
***************HR面流程结束***************
***************录用流程开始***************
技术部的任务:name:录用,发放Offer,id:20
李四的任务数量:1
李四的任务:name:录用,发放Offer,id:20
李四的任务数量:0
***************录用流程结束***************
流程结束时间:Wed Jul 31 16:35:45 CST 2013
一、搭建开发环境
1、安装jdk5+
2、安装eclipse
3、安装eclipse BPMN designer plugin,地址:http://activiti.org/designer/update/
4、下载Activiti5,地址:http://activiti.org/download.html
5、建立项目,添加jar包:
activation-1.1.jar
activiti-engine-5.9.jar
activiti-spring-5.9-sources.jar
activiti-spring-5.9.jar
aopalliance-1.0.jar
commons-dbcp-1.4.jar
commons-email-1.2.jar
commons-lang-2.4.jar
commons-logging-1.1.1.jar
commons-pool-1.3.jar
livetribe-jsr223-2.0.6.jar
mail-1.4.1.jar
mybatis-3.0.6.jar
spring-aop-3.0.3.RELEASE.jar
spring-asm-3.0.3.RELEASE.jar
spring-beans-3.0.3.RELEASE.jar
spring-context-3.0.3.RELEASE.jar
spring-core-3.0.3.RELEASE.jar
spring-expression-3.0.3.RELEASE.jar
spring-jdbc-3.0.3.RELEASE.jar
spring-orm-3.0.3.RELEASE.jar
spring-test-3.0.3.RELEASE.jar
spring-tx-3.0.3.RELEASE.jar
6、安装数据库,可以选择以下一种,
Activiti database type | Versions tested | Example JDBC URL | Notes |
---|---|---|---|
h2 | 1.2.132 | jdbc:h2:tcp://localhost/activiti | Default configured database |
mysql | 5.1.11 | jdbc:mysql://localhost:3306/activiti?autoReconnect=true | Tested using mysql-connetor-java database driver |
oracle | 10.2.0 | jdbc:oracle:thin:@localhost:1521:xe | |
postgres | 8.4 | jdbc:postgresql://localhost:5432/activiti | |
db2 | DB2 9.7 using db2jcc4 | jdbc:db2://localhost:50000/activiti | [EXPERIMENTAL] |
mssql | 2008 using JDBC jtds-1.2.4 | jdbc:jtds:sqlserver://localhost:1433/activiti | [EXPERIMENTAL] |
7、加入相应的数据库驱动jar包,以及数据源支持。
OK,到这里,开发环境已经搭建完成,下面进入开发阶段。
二、开发概述使用Activiti5和Spring集成。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> <property name="driverClass" value="org.h2.Driver" /> <property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" /> <property name="username" value="sa" /> <property name="password" value="123456" /> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"> <property name="dataSource" ref="dataSource" /> <property name="transactionManager" ref="transactionManager" /> <property name="databaseSchemaUpdate" value="true" /> <!-- 是否更新数据库结构,如果表不存在,启动时会自动创建 --> <property name="jobExecutorActivate" value="false" /> </bean> <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"> <property name="processEngineConfiguration" ref="processEngineConfiguration" /> </bean>
3、运行代码:
public static void main(String args[]) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("activiti-conf.xml"); //初始化spring上下文
ProcessEngine processEngine = (ProcessEngine) ctx.getBean("processEngine"); //获得Activiti主接口
System.out.println("processEngine name :" + processEngine.getName());
RepositoryService repositoryService = processEngine.getRepositoryService(); //获得资源操作接口
RuntimeService runtimeService = (RuntimeService) processEngine.getRuntimeService(); //获得运行时操作接口(大多操作流程实例)
TaskService taskService = processEngine.getTaskService(); //获得任务操作接口
IdentityService identityService = processEngine.getIdentityService(); //获得身份操作接口(用户和用户组)
HistoryService historyService = processEngine.getHistoryService(); //获得历史查询接口
FormService formService = processEngine.getFormService(); //获得表单数据绑定接口
ManagementService managementService = processEngine.getManagementService(); //获得管理接口
Deployment deployment = repositoryService.createDeployment().addClasspathResource("demo.bpmn20.xml").deploy();//部署流程定义
System.out.print("发布流程定义成功!" + " Id=" + deployment.getId() + ", Name=" + deployment.getName());
}
如果执行成功,说明Activiti已经于spring成功集成。
同时,数据库中会产生相应的表。
4、表说明
RE:RepositoryService接口所操作的表
ACT_RE_DEPLOYMENT部署流程定义时需要被持久化保存下来的信息
ACT_RE_PROCDEF 流程定义数据表
ID:IdentityService接口所操作的表
ACT_ID_INFO 用户扩展信息表
ACT_ID_MEMBERSHIP 用户与分组对应信息表
ACT_ID_GROUP 用户组信息
ACT_ID_USER 用户信息
RU:运行时表 - RuntimeService
ACT_RU_VARIABLE 运行时流程变量表
ACT_RU_TASK 任务节点表
ACT_RU_JOB 定时任务表
ACT_RU_IDENTITYLINK 任务参与者表。主要存储任务节点与参与者的相关信息
ACT_RU_EXECUTION 流程执行路径信息
HI:历史数据表,HistoryService
ACT_HI_PROCINST 历史流程实例表
ACT_HI_ATTACHMENT 历史附件表
ACT_HI_COMMENT 历史注释表
ACT_HI_DETAIL 历史详情表
ACT_HI_TASKINST 历史任务实例表
ACT_HI_ACTINST 历史执行路径信息
GE:全局数据
ACT_GE_BYTEARRAY 二进制数据表:流程定义图片和xml、Serializable的变量
ACT_GE_PROPERTY 属性数据表。存储整个流程引擎级别的数据
注:由于Activiti会在任务或者流程结束时,删除其所在的运行时数据,存入历史数据表。所以保证了运行时表小且快。不会有性能问题。
5、涉及到的名词,对应类,解释
流程定义:ProcessDefinition类,也就是我们用设计器生成的xml文件,Activiti将根据流程定义产生流程实例。
流程实例:ProcessInstance类,是一个完整的流程表示。
流程执行路径:Execution类, 表示流程的执行实例。
任务节点:Task类,有很多这里不一一介绍
参与者:User,参与人
注:如果同一个流程定义被发布多次,那么Activiti将默认采用最新版本。
注: Activiti中关于 流程实例 和 流程执行实例 的区别
ProcessInstance是流程实例,Execution是流程的一个执行实例。一个流程在并发分支的情况下,会产生多个执行实例,一个Execution也可以分出多个Execution。
又有:ProcessInstance extends Execution,说明ProcessInstance也是一个Execution,
Execution的 Parent Execution可能是一个ProcessInstance,所以,在流程没有并发分支的情况下ProcessInstance与Execution是相同的。
三、接口介绍
RepositoryService :流程定义发布、查询、管理相关操作的接口
//查询所有已发布信息
List<Deployment> ds = repositoryService.createDeploymentQuery().list();// 查询所有最新版本的流程定义
List<ProcessDefinition> pds = repositoryService.createProcessDefinitionQuery().latestVersion().list();//发布流程定义
DeploymentBuilder builder = repositoryService.createDeployment();
builder = builder.addClasspathResource(definitionResource);
Deployment deployment = builder.deploy();