程序员人生 网站导航

工作流框架Activiti常用功能初探

栏目:综合技术时间:2016-07-13 08:26:49

Activiti项目是1项新的基于Apache许可的开源BPM平台,从基础开始构建,旨在提供支持新的BPMN 2.0标准,包括支持对象管理组(OMG),面对新技术的机遇,诸如互操作性和云架构,提供技术实现。

BPMN是由BPMI(The Business Process Management Initiative)开发了1套标准叫业务流程建模符号(BPMN - Business Process Modeling Notation)BPMN定义了1个业务流程图(Business Process Diagram),该业务流程图基于1个流程图(flowcharting),该流程图被设计用于创建业务流程操作的图形化模型。而1个业务流程模型(Business Process Model),指1个由的图形对象(graphical objects)组成的网状图,图形对象包括活动(acticities)和用于定义这些活动履行顺序的流程控制器(flow controls)。

以下是对Activiti框架几个经常使用功能的测试。

环境:mysql,eclipse,jdk1.7,activiti5.13

首先将Activiti相干的JAR包导入到项目中,由于JAR众多,这里就不罗列了。主要记录代码部份。

1.在eclipse中安装Activiti插件

Help -> InstallNew Software,在以下Install界面板中,点击Add按钮

然后在Name和Location中分别填入以下内容:

Name: Activiti BPMN 2.0 designer

Location: http://activiti.org/designer/update/

然后1直下1步、下1步安装,根据提示重启eclipse


重启后,再打开菜单Windows->Preferences->Activiti->Save下流程流程图片的生成方式



2.配置log4j,让其打印出sql语句

在项目根目录下创建log4j.properties文件,在此文件中输入以下配置信息
### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.err log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file mylog.log ### log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=c:\mylog.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### set log levels - for more verbose logging change 'info' to 'debug' ### log4j.rootLogger=debug, stdout

3.activiti-context.xml配置activiti

在项目根目录创建activiti-context.xml文件,在其中配置以下内容
其中的activitiStudy数据库名,须自己提早创建好。
<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⑵.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx⑶.0.xsd"> <!-- 配置流程引擎配置对象 --> <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <property name="jdbcDriver" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql:///activitiStudy?useUnicode=true&characterEncoding=UTF⑻"/> <property name="jdbcUsername" value="root" /> <property name="jdbcPassword" value="root" /> <property name="databaseSchemaUpdate" value="true" /> </bean> <!-- 配置1个流程引擎工厂bean,用于创建流程引擎对象 --> <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"> <!-- 通过set方法注入流程引擎配置对象 --> <property name="processEngineConfiguration" ref="processEngineConfiguration" /> </bean> </beans>

4.画流程图

在项目中,在项目根目录下,点击new->other->选择Activiti下的Activiti Diagram新建1个流程图。

在其中画以下图示

并设好相干属性



5.Activiti测试代码

import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.DeploymentBuilder; import org.activiti.engine.repository.DeploymentQuery; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinitionQuery; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.runtime.ProcessInstanceQuery; import org.activiti.engine.task.Task; import org.activiti.engine.task.TaskQuery; import org.apache.commons.io.FileUtils; import org.junit.Test; /** * 使用Activiti框架的API操作流程 * * @author PuHaiyang * @createTime 2016年6月28日 下午4:50:39 * @email 761396462@qq.com * @function Activiti基本功能测试 * */ public class MyActivitiAPITest { ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); @Test public void deployActiviti() { // 如果之前没有创建activiti相干的表,调用它会自动创建,由activiti-context.xml文件内容创建 DeploymentBuilder deploymentBuilder = processEngine.getRepositoryService().createDeployment(); deploymentBuilder.addClasspathResource("MyTest.bpmn"); deploymentBuilder.addClasspathResource("MyTest.png"); deploymentBuilder.name("i_am_name"); Deployment deploy = deploymentBuilder.deploy(); System.out.println(deploy.getId()); // 部署信息表 insert into ACT_RE_DEPLOYMENT(ID_, NAME_, CATEGORY_, // DEPLOY_TIME_) values(?, ?, ?, ?) // 2进制数据表,bpmn文件插入 insert into ACT_GE_BYTEARRAY(ID_, REV_, NAME_, // BYTES_, DEPLOYMENT_ID_, GENERATED_) values (?, 1, ?, ?, ?, ?) // 2进制数据表,png文件插入 insert into ACT_GE_BYTEARRAY(ID_, REV_, NAME_, BYTES_, // DEPLOYMENT_ID_, GENERATED_) values (?, 1, ?, ?, ?, ?) // 流程定义数据表 insert into ACT_RE_PROCDEF(ID_, REV_, CATEGORY_, NAME_, KEY_, // VERSION_, DEPLOYMENT_ID_, RESOURCE_NAME_, DGRM_RESOURCE_NAME_, // DESCRIPTION_, HAS_START_FORM_KEY_, SUSPENSION_STATE_) values (?, 1, // ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) } /** * 查询部署列表 */ @Test public void queryDeployment() { DeploymentQuery deploymentQuery = processEngine.getRepositoryService().createDeploymentQuery(); List<Deployment> list = deploymentQuery.list(); for (Deployment deployment : list) { String id = deployment.getId(); System.out.println(id); } } /** * 删除部署信息 */ @Test public void deleteDeployment() { String deploymentId = "1"; // 第2个参数代表级联操作 processEngine.getRepositoryService().deleteDeployment(deploymentId, true); // 删除所有相干的activiti信息 } /** * 查询1次部署对应的流程定义文件名称和对应的输入流(bpmn png) * * @throws Exception */ @Test public void queryDeploymentResource() throws Exception { String deploymentId = "101"; List<String> names = processEngine.getRepositoryService().getDeploymentResourceNames(deploymentId); for (String name : names) { System.out.println(name); InputStream in = processEngine.getRepositoryService().getResourceAsStream(deploymentId, name); // 将文件保存到本地磁盘 // FileUtils来自commons-io-xxx.jar FileUtils.copyInputStreamToFile(in, new File("d:\\" + name)); in.close(); } } /** * 取得流程表中流程图 * * @throws Exception */ @Test public void getProcessDiagream() throws Exception { String processDefinitionId = "myProcess:1:104"; InputStream pngInputStream = processEngine.getRepositoryService().getProcessDiagram(processDefinitionId); FileUtils.copyInputStreamToFile(pngInputStream, new File("d:\\my.png")); } /** * 启动流程实例 <br> * 方式1:根据流程定义的id启动 <br> * 方式2:根据流程定义的key启动(自动选择最新版本的流程定义启动流程实例) */ @Test public void startProcess() { /* * 方式1:根据流程定义的id启动 String processDefinitionId = "myProcess:1:104"; * ProcessInstance processInstance = * processEngine.getRuntimeService().startProcessInstanceById * (processDefinitionId ); System.out.println(processInstance.getId()); */ // 方式2:根据流程定义的key启动(自动选择最新版本的流程定义启动流程实例) String processDefinitionKey = "myProcess"; ProcessInstance processInstance = processEngine.getRuntimeService() .startProcessInstanceByKey(processDefinitionKey); System.out.println(processInstance.getId()); // 调用SQL语句以下 // 1 ACT_RU_EXECUTION 运行时流程履行实例表 // insert into ACT_RU_EXECUTION (ID_, REV_, PROC_INST_ID_, // BUSINESS_KEY_, PROC_DEF_ID_, ACT_ID_, IS_ACTIVE_, IS_CONCURRENT_, // IS_SCOPE_,IS_EVENT_SCOPE_, PARENT_ID_, SUPER_EXEC_, // SUSPENSION_STATE_, CACHED_ENT_STATE_) values ( ?, 1, ?, ?, ?, ?, ?, // ?, ?, ?, ?, ?, ?, ? ) // 2 ACT_HI_PROCINST 历史流程实例表 // insert into ACT_HI_PROCINST ( ID_, PROC_INST_ID_, BUSINESS_KEY_, // PROC_DEF_ID_, START_TIME_, END_TIME_, DURATION_, START_USER_ID_, // START_ACT_ID_, END_ACT_ID_, SUPER_PROCESS_INSTANCE_ID_, // DELETE_REASON_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) // 3 ACT_HI_ACTINST 历史节点表 // insert into ACT_HI_ACTINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, // EXECUTION_ID_, ACT_ID_, TASK_ID_, CALL_PROC_INST_ID_, ACT_NAME_, // ACT_TYPE_, ASSIGNEE_, START_TIME_, END_TIME_, DURATION_ ) values ( ?, // ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) // 4 ACT_HI_ACTINST 历史节点表 // insert into ACT_HI_ACTINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, // EXECUTION_ID_, ACT_ID_, TASK_ID_, CALL_PROC_INST_ID_, ACT_NAME_, // ACT_TYPE_, ASSIGNEE_, START_TIME_, END_TIME_, DURATION_ ) values ( ?, // ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) // 5 ACT_RU_TASK 运行时任务节点表 // insert into ACT_RU_TASK (ID_, REV_, NAME_, PARENT_TASK_ID_, // DESCRIPTION_, PRIORITY_, CREATE_TIME_, OWNER_, ASSIGNEE_, // DELEGATION_, EXECUTION_ID_, PROC_INST_ID_, PROC_DEF_ID_, // TASK_DEF_KEY_, DUE_DATE_, SUSPENSION_STATE_) values (?, 1, ?, ?, ?, // ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) // 6 ACT_HI_TASKINST 历史任务实例表 // insert into ACT_HI_TASKINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, // EXECUTION_ID_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, OWNER_, // ASSIGNEE_, START_TIME_, CLAIM_TIME_, END_TIME_, DURATION_, // DELETE_REASON_, TASK_DEF_KEY_, FORM_KEY_, PRIORITY_, DUE_DATE_ ) // values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) // 7 ACT_RU_IDENTITYLINK 运行时流程人员表,主要存储任务节点与参与者的相干信息 // insert into ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, // GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_) values (?, 1, ?, ?, // ?, ?, ?, ?) // 8 ACT_HI_IDENTITYLINK 历史流程人员表 // insert into ACT_HI_IDENTITYLINK (ID_, TYPE_, USER_ID_, GROUP_ID_, // TASK_ID_, PROC_INST_ID_) values (?, ?, ?, ?, ?, ?) } /** * 查询流程实例列表,查询act_ru_execution表 */ @Test public void queryRuntimeProcess() { // 流程实例查询对象,查询act_ru_execution表 ProcessInstanceQuery query = processEngine.getRuntimeService().createProcessInstanceQuery(); query.processDefinitionKey("myProcess"); query.orderByProcessInstanceId().desc(); query.listPage(0, 2); List<ProcessInstance> list = query.list(); for (ProcessInstance pi : list) { System.out.println(pi.getId() + " " + pi.getActivityId()); } } /** * 不通过<br> * 删除流程实例 */ @Test public void deleteProcess() { String processInstanceId = "201"; processEngine.getRuntimeService().deleteProcessInstance(processInstanceId, "不准逃课!"); // 履行删除部份SQL以下 // 1 ACT_RU_TASK 运行时任务节点表 // delete from ACT_RU_TASK where ID_ = ? and REV_ = ? // 2 ACT_RU_IDENTITYLINK 运行时流程人员表,主要存储任务节点与参与者的相干信息 // delete from ACT_RU_IDENTITYLINK where ID_ = ? // 3 ACT_RU_EXECUTION 运行时流程履行实例表 // delete from ACT_RU_EXECUTION where ID_ = ? and REV_ = ? // 履行更新部份SQL以下 // 1 ACT_HI_PROCINST 历史流程实例表 // update ACT_HI_PROCINST set PROC_DEF_ID_ = ?, START_TIME_ = ?, // END_TIME_ = ?, DURATION_ = ?, END_ACT_ID_ = ?, DELETE_REASON_ = ? // where ID_ = ? // 2 ACT_HI_ACTINST 历史节点表 // update ACT_HI_ACTINST set EXECUTION_ID_ = ?, ASSIGNEE_ = ?, END_TIME_ // = ?, DURATION_ = ? where ID_ = ? // 3 ACT_HI_TASKINST 历史任务实例表 // update ACT_HI_TASKINST set EXECUTION_ID_ = ?, NAME_ = ?, // PARENT_TASK_ID_ = ?, DESCRIPTION_ = ?, OWNER_ = ?, ASSIGNEE_ = ?, // CLAIM_TIME_ = ?, END_TIME_ = ?, DURATION_ = ?, DELETE_REASON_ = ?, // TASK_DEF_KEY_ = ?, FORM_KEY_ = ?, PRIORITY_ = ?, DUE_DATE_ = ? where // ID_ = ? } /** * 查询任务 */ @Test public void queryTask() { // 任务查询对象,查询act_ru_task表 TaskQuery query = processEngine.getTaskService().createTaskQuery(); String assignee = "班主任"; query.taskAssignee(assignee); query.orderByTaskCreateTime().desc(); List<Task> list = query.list(); for (Task task : list) { System.out.println(task.getId()); } // 履行sql以下 // 1 ACT_GE_PROPERTY 属性数据表存储全部流程引擎级别的数据,初始化表结构时,会默许插入3条记录, // select * from ACT_GE_PROPERTY where NAME_ = ? // 2 ACT_RU_TASK 运行时任务节点表 // select distinct RES.* from ACT_RU_TASK RES WHERE RES.ASSIGNEE_ = ? // order by RES.CREATE_TIME_ desc LIMIT ? OFFSET ? } /** * 处理任务 */ @Test public void completeTask() { String taskId = "304"; processEngine.getTaskService().complete(taskId); // 履行的主要SQL以下 // 1 ACT_GE_PROPERTY 属性数据表存储全部流程引擎级别的数据,初始化表结构时,会默许插入3条记录 // update ACT_GE_PROPERTY SET REV_ = ?, VALUE_ = ? where NAME_ = ? and // REV_ = ? // 2 ACT_HI_ACTINST 历史节点表 // insert into ACT_HI_ACTINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, // EXECUTION_ID_, ACT_ID_, TASK_ID_, CALL_PROC_INST_ID_, ACT_NAME_, // ACT_TYPE_, ASSIGNEE_, START_TIME_, END_TIME_, DURATION_ ) values ( ?, // ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) // 3 ACT_RU_TASK 运行时任务节点表 // insert into ACT_RU_TASK (ID_, REV_, NAME_, PARENT_TASK_ID_, // DESCRIPTION_, PRIORITY_, CREATE_TIME_, OWNER_, ASSIGNEE_, // DELEGATION_, EXECUTION_ID_, PROC_INST_ID_, PROC_DEF_ID_, // TASK_DEF_KEY_, DUE_DATE_, SUSPENSION_STATE_) values (?, 1, ?, ?, ?, // ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) // 4 ACT_HI_TASKINST 历史任务实例表 // insert into ACT_HI_TASKINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, // EXECUTION_ID_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, OWNER_, // ASSIGNEE_, START_TIME_, CLAIM_TIME_, END_TIME_, DURATION_, // DELETE_REASON_, TASK_DEF_KEY_, FORM_KEY_, PRIORITY_, DUE_DATE_ ) // values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) // 5 ACT_RU_IDENTITYLINK 运行时流程人员表,主要存储任务节点与参与者的相干信息 // insert into ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, // GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_) values (?, 1, ?, ?, // ?, ?, ?, ?) // 6 ACT_HI_IDENTITYLINK 历史流程人员表 // insert into ACT_HI_IDENTITYLINK (ID_, TYPE_, USER_ID_, GROUP_ID_, // TASK_ID_, PROC_INST_ID_) values (?, ?, ?, ?, ?, ?) // 7 ACT_HI_TASKINST 历史任务实例表 // update ACT_HI_TASKINST set EXECUTION_ID_ = ?, NAME_ = ?, // PARENT_TASK_ID_ = ?, DESCRIPTION_ = ?, OWNER_ = ?, ASSIGNEE_ = ?, // CLAIM_TIME_ = ?, END_TIME_ = ?, DURATION_ = ?, DELETE_REASON_ = ?, // TASK_DEF_KEY_ = ?, FORM_KEY_ = ?, PRIORITY_ = ?, DUE_DATE_ = ? where // ID_ = ? // 8 ACT_RU_EXECUTION 运行时流程履行实例表 // update ACT_RU_EXECUTION set REV_ = ?, PROC_DEF_ID_ = ?, ACT_ID_ = ?, // IS_ACTIVE_ = ?, IS_CONCURRENT_ = ?, IS_SCOPE_ = ?, IS_EVENT_SCOPE_ = // ?, PARENT_ID_ = ?, SUPER_EXEC_ = ?, SUSPENSION_STATE_ = ?, // CACHED_ENT_STATE_ = ? where ID_ = ? and REV_ = ? // 9 ACT_HI_ACTINST 历史节点表 // update ACT_HI_ACTINST set EXECUTION_ID_ = ?, ASSIGNEE_ = ?, END_TIME_ // = ?, DURATION_ = ? where ID_ = ? // 10 ACT_RU_TASK 运行时任务节点表 // delete from ACT_RU_TASK where ID_ = ? and REV_ = ? } /** * 直接将流程向下履行1步 */ @Test public void signal() { String executionId = "301";// 流程实例id processEngine.getRuntimeService().signal(executionId); } /** * 查询最新版本的流程定义列表 */ @Test public void getLastTasks() { ProcessDefinitionQuery query = processEngine.getRepositoryService().createProcessDefinitionQuery(); query.orderByProcessDefinitionVersion().asc(); List<ProcessDefinition> list = query.list(); Map<String, ProcessDefinition> map = new HashMap<String, ProcessDefinition>(); for (ProcessDefinition pd : list) { map.put(pd.getKey(), pd); } ArrayList<ProcessDefinition> lastList = new ArrayList<>(map.values()); for (ProcessDefinition processDefinition : lastList) { System.out.println(processDefinition.getName() + " " + processDefinition.getVersion()); } } }



------分隔线----------------------------

上一篇 数据流中的中位数

下一篇 HTTP详解

------分隔线----------------------------

最新技术推荐