Activiti学习记录(二)
1.初始化数据库
使用工作流引擎创建23张表
public class TestActiviti {
/**
* 使用代码创建工作流需要的23张表
*/
@Test
public void createTable() {
ProcessEngineConfiguration createStandaloneProcessEngineConfiguration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
createStandaloneProcessEngineConfiguration.setJdbcDriver("com.mysql.jdbc.Driver");
createStandaloneProcessEngineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/activiti0710?useUnicode=true&characterEncoding=utf8");
createStandaloneProcessEngineConfiguration.setJdbcUsername("root"); /**
public static final String DB_SCHEMA_UPDATE_FALSE = "false"; 不能自动创建表,需要表存在
public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop"; 表示先删除表,在创建表
public static final String DB_SCHEMA_UPDATE_TRUE = "true";如果表不存在,自动创建表
*/
createStandaloneProcessEngineConfiguration.setDatabaseSchemaUpdate(createStandaloneProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
//工作流的核心对象
ProcessEngine buildProcessEngine = createStandaloneProcessEngineConfiguration.buildProcessEngine();
System.out.println(buildProcessEngine); }
}
在Activiti中,在创建核心的流程引擎对象时会自动建表。如果程序正常执行,mysql会自动建库,然后创建23张表。
2.添加并制定配置文件
在Actiiti5中定制流程必定会操作到数据库,如果都像上面那样写一大段代码会非常麻烦,所以我们可以把数据库连接配置写入配置文件。
创建activiti.cfg.xml文件,配置
<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"> <!--
ProcessEngineConfiguration createStandaloneProcessEngineConfiguration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
createStandaloneProcessEngineConfiguration.setJdbcDriver("com.mysql.jdbc.Driver");
createStandaloneProcessEngineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/activiti0710?useUnicode=true&characterEncoding=utf8");
createStandaloneProcessEngineConfiguration.setJdbcUsername("root"); /**
public static final String DB_SCHEMA_UPDATE_FALSE = "false"; 不能自动创建表,需要表存在
public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop"; 表示先删除表,在创建表
public static final String DB_SCHEMA_UPDATE_TRUE = "true";如果表不存在,自动创建表
*/
createStandaloneProcessEngineConfiguration.setDatabaseSchemaUpdate(createStandaloneProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
//工作流的核心对象
ProcessEngine buildProcessEngine = createStandaloneProcessEngineConfiguration.buildProcessEngine(); -->
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
<!-- 连接数据库配置 -->
<property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti0710?useUnicode=true&characterEncoding=utf8"></property>
<property name="jdbcUsername" value="root"></property>
<!-- 没有表创建表 -->
<property name="databaseSchemaUpdate" value="true"></property>
</bean> </beans>
java代码:
/**
* 使用配置文件创建工作流需要的23张表
*/
@Test
public void createTable_2() {
ProcessEngineConfiguration createProcessEngineConfigurationFromResource = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine buildProcessEngine = createProcessEngineConfigurationFromResource.buildProcessEngine();
System.out.println(buildProcessEngine);
}
3. HelloWorld程序(模拟流程的执行)
先新建一个bpmn文件
编写junit测试类
public class helloWorld { ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
* 部署流程定义
*/
@Test
public void deployProcessDefinition() {
Deployment deploy = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
.createDeployment()//创建一个部署对象
.name("helloWorld入门程序")//添加部署的名称
.addClasspathResource("diagrams/HelloWorld.bpmn")//一次只能加载一个文件
.addClasspathResource("diagrams/HelloWorld.png")
.deploy();//完成部署
System.out.println(deploy.getId());
System.out.println(deploy.getName());
} /**
* 启动流程实例
*/
@Test
public void startProcessInstance() {
//流程定义的key
String processDefinitionKey = "helloWorld";
ProcessInstance startProcessInstanceByKey = processEngine.getRuntimeService()//与正在执行的流程实例和执行对象相关的Service
.startProcessInstanceByKey(processDefinitionKey);//使用流程定义的key启动流程实例,key对应HelloWorld.bpmn中的id属性,使用key启动,默认是最新版本的流程定义启动
System.out.println("流程实例id" + startProcessInstanceByKey.getId());//流程实例id
System.out.println("流程定义id" + startProcessInstanceByKey.getProcessDefinitionId());//流程定义id
} /**
* 查询当前人的个人任务
*/
@Test
public void findMyPersonTask() {
String assignee = "王五";
List<Task> list = processEngine.getTaskService()//与正在执行的任务管理相关的service
.createTaskQuery()//创建任务查询对象
.taskAssignee(assignee)//指定个人任务查询,指定办理人
.list();
if (list != null && list.size() > 0) {
for (Task task : list) {
System.out.println("任务ID:"+task.getId());
System.out.println("任务名称:"+task.getName());
System.out.println("任务创建时间:"+task.getCreateTime());
System.out.println("任务办理人:"+task.getAssignee());
System.out.println("流程实例ID:"+task.getProcessInstanceId());
System.out.println("执行对象ID:"+task.getExecutionId());
System.out.println("流程定义ID:"+task.getProcessDefinitionId());
}
}
} /**
* 完成个人任务
*/
@Test
public void completMyPersonTask() {
String taskId = "302";
processEngine.getTaskService()//与正在执行的任务管理相关的service
.complete(taskId);
System.out.println("完成任务:任务ID"+taskId);
}
}
4.部署流程定义(classpath路径加载文件)
说明:
1) 先获取流程引擎对象:在创建时会自动加载classpath下的activiti.cfg.xml
2) 首先获得默认的流程引擎,通过流程引擎获取了一个RepositoryService对象(仓库对象)
3) 由仓库的服务对象产生一个部署对象配置对象,用来封装部署操作的相关配置。
4) 这是一个链式编程,在部署配置对象中设置显示名,上传流程定义规则文件
5) 向数据库表中存放流程定义的规则信息。
6) 这一步在数据库中将操作三张表:
a) act_re_deployment(部署对象表)
存放流程定义的显示名和部署时间,每部署一次增加一条记录
b) act_re_procdef(流程定义表)
存放流程定义的属性信息,部署每个新的流程定义都会在这张表中增加一条记录。
注意:当流程定义的key相同的情况下,使用的是版本升级
c) act_ge_bytearray(资源文件表)
存储流程定义相关的部署信息。即流程定义文档的存放地。每部署一次就会增加两条记录,一条是关于bpmn规则文件的,一条是图片的(如果部署时只指定了bpmn一个文件,activiti会在部署时解析bpmn文件内容自动生成流程图)。两个文件不是很大,都是以二进制形式存储在数据库中。
/**
* 部署流程定义(从classpath)
*/
@Test
public void deployProcessDefinition_classpath() {
Deployment deploy = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
.createDeployment()//创建一个部署对象
.name("流程定义")//添加部署的名称
.addClasspathResource("diagrams/HelloWorld.bpmn")//一次只能加载一个文件
.addClasspathResource("diagrams/HelloWorld.png")
.deploy();//完成部署
System.out.println(deploy.getId());
System.out.println(deploy.getName());
}
5. 部署流程定义(zip格式文件)
/**
* 部署流程定义(从zip)
*/
@Test
public void deployProcessDefinition_zip() {
InputStream in = this.getClass().getClassLoader().getResourceAsStream("diagrams/HelloWorld.zip");
ZipInputStream zipInputStream = new ZipInputStream(in);
Deployment deploy = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
.createDeployment()//创建一个部署对象
.name("流程定义")//添加部署的名称
.addZipInputStream(zipInputStream)//一次只能加载一个文件
.deploy();//完成部署
System.out.println(deploy.getId());
System.out.println(deploy.getName());
}
6. 查看流程定义
查询流程定义的信息
/**
* 查询流程定义
*/
@Test
public void findProcessDefinition() {
List<ProcessDefinition> list = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
.createProcessDefinitionQuery()//创建流程定义查询
// .deploymentId(deploymentId) //使用部署对象ID查询
// .processDefinitionKey(processDefinitionKey) //使用流程定义的key查询
// .processDefinitionId(processDefinitionId) //使用流程定义的id查询
// .processDefinitionKeyLike(processDefinitionKeyLike) //使用流程定义的id模糊查询
// .processDefinitionNameLike(processDefinitionNameLike) //使用流程定义的name模糊查询
/** 排序 **/
.orderByProcessDefinitionVersion().asc() //按照版本升序排列
// .orderByProcessDefinitionName().desc() // 按照流程定义的名称降序排序
.list(); //返回一个集合列表,封装流程定义
// .singleResult() //返回唯一结果集
// .listPage(firstResult, maxResults) //分页查询
// .count() //返回结果集数量
if (list != null && list.size() > 0) {
for (ProcessDefinition pd : list) {
System.out.println("流程定义ID:"+ pd.getId());//流程定义的key+版本+随机生成数
System.out.println("流程定义的名称:"+pd.getName());//对应helloworld.bpmn文件中的name属性值
System.out.println("流程定义的key:"+pd.getKey());//对应helloworld.bpmn文件中的id属性值
System.out.println("流程定义的版本"+pd.getVersion());//当流程定义的key相同时,版本从1开始逐次升级
System.out.println("资源名称bpmn文件:"+pd.getResourceName());
System.out.println("资源名称png文件:"+pd.getDiagramResourceName());
System.out.println("部署对象ID:"+pd.getDeploymentId());
}
} }
说明:
1) 流程定义和部署对象相关的Service都是RepositoryService。
2) 创建流程定义查询对象,可以在ProcessDefinitionQuery上设置查询的相关参数
3) 调用ProcessDefinitionQuery对象的list方法,执行查询,获得符合条件的流程定义列表
4) 由运行结果可以看出:
Key和Name的值为:bpmn文件process节点的id和name的属性值
5) key属性被用来区别不同的流程定义。
6) 带有特定key的流程定义第一次部署时,version为1。之后每次部署都会在当前最高版本号上加1
7) Id的值的生成规则为:{processDefinitionKey}:{processDefinitionVersion}:{generated-id}, 这里的generated-id是一个自动生成的唯一的数字
8) 重复部署一次,deploymentId的值以一定的形式变化
规则act_ge_property表生成
7.删除流程定义
删除部署到activiti中的流程定义。
/**
* 删除流程定义
*/
@Test
public void delProcessDefinition() {
//使用部署ID,完成删除
String deploymentId = "601";
/**
* 不带级联删除
* 只能删除没有启动的流程,如果流程启动,就会抛出异常
*/
/*processEngine.getRepositoryService()
.deleteDeployment(deploymentId);*/
/**
* 级联删除
* 不管流程是否启动,都能删除
*/
processEngine.getRepositoryService()
.deleteDeployment(deploymentId, true);
System.out.println("删除成功!");
}
8. 获取流程定义文档的资源(查看流程图附件)
查询出流程定义文档。主要查的是图片,用于显示流程用。
/**
* 查看流程图
* @throws IOException
*/
@Test
public void viewPic() throws IOException {
//将生成的图片放置到文件夹下
String deploymentId = "901";
//获取图片资源名称
List<String> list = processEngine.getRepositoryService()
.getDeploymentResourceNames(deploymentId);
String resourceName = "";
if (list != null && list.size() > 0) {
for (String name : list) {
if (name.indexOf(".png") >= 0) {
resourceName = name;
} }
} //获取图片输入流
InputStream in = processEngine.getRepositoryService()
.getResourceAsStream(deploymentId, resourceName); //将图片生成到D盘目录下
File file = new File("D:/"+resourceName);
FileUtils.copyInputStreamToFile(in, file);
}
说明:
1) deploymentId为流程部署ID
2) resourceName为act_ge_bytearray表中NAME_列的值
3) 使用repositoryService的getDeploymentResourceNames方法可以获取指定部署下得所有文件的名称
4) 使用repositoryService的getResourceAsStream方法传入部署ID和资源图片名称可以获取部署下指定名称文件的输入流
最后的有关IO流的操作,使用FileUtils工具的copyInputStreamToFile方法完成流程流程到文件的拷贝,将资源文件以流的形式输出到指定文件夹下
9.流程定义是无法修改的
控制修改:使用流程定义的key相同情况下,版本升级
10.附加功能:查询最新版本的流程定义
/**
* 附加功能:查询最新版本的流程定义
*/
@Test
public void findLastVersionProcessDefinition() {
List<ProcessDefinition> list = processEngine.getRepositoryService()
.createProcessDefinitionQuery()
.orderByProcessDefinitionVersion().desc()//使用流程定义的版本升序排列
.list(); /**
* map集合的key:流程定义的key
* map集合的value:流程定义的对象
* map集合的特点:当map集合key相同的情况下,后一次的值将替换前一次的值
*/
Map<String, ProcessDefinition> map = new LinkedHashMap<>();
if (list != null && list.size() > 0) {
for (ProcessDefinition pd : list) {
map.put(pd.getKey(), pd);
}
}
List<ProcessDefinition> pdList = new ArrayList<ProcessDefinition>(map.values());
if (pdList != null && pdList.size() > 0) {
for (ProcessDefinition pd : pdList) {
System.out.println("流程定义ID:"+ pd.getId());//流程定义的key+版本+随机生成数
System.out.println("流程定义的名称:"+pd.getName());//对应helloworld.bpmn文件中的name属性值
System.out.println("流程定义的key:"+pd.getKey());//对应helloworld.bpmn文件中的id属性值
System.out.println("流程定义的版本:"+pd.getVersion());//当流程定义的key相同时,版本从1开始逐次升级
System.out.println("资源名称bpmn文件:"+pd.getResourceName());
System.out.println("资源名称png文件:"+pd.getDiagramResourceName());
System.out.println("部署对象ID:"+pd.getDeploymentId());
}
}
}
11.附加功能:删除流程定义(删除key相同的所有不同版本的流程定义)
/**
* 附加功能: 删除流程定义(删除key相同的所有流程版本不同的流程定义)
*/
@Test
public void delProcessDefinitionByKey() {
//流程定义的key
String processDefinitionKey = "helloWorld";
//先使用流程定义的key查询流程定义,查询所有的版本
List<ProcessDefinition> list = processEngine.getRepositoryService()
.createProcessDefinitionQuery()
.processDefinitionKey(processDefinitionKey)
.list();
if (list != null && list.size() > 0) {
for (ProcessDefinition pd : list) {
String deploymentId = pd.getDeploymentId();
processEngine.getRepositoryService().deleteDeployment(deploymentId, true);
}
}
}
12.流程实例,任务和执行
Execution 执行对象
按流程定义的规则执行一次的过程.
对应的表:
act_ru_execution: 正在执行的信息
act_hi_procinst:已经执行完的历史流程实例信息
act_hi_actinst:存放历史所有完成的活动
ProcessInstance 流程实例
特指流程从开始到结束的那个最大的执行分支,一个执行的流程中,流程实例只有1个。
注意
(1)如果是单例流程,执行对象ID就是流程实例ID
(2)如果一个流程有分支和聚合,那么执行对象ID和流程实例ID就不相同
(3)一个流程中,流程实例只有1个,执行对象可以存在多个。
Task 任务
执行到某任务环节时生成的任务信息。
对应的表:
act_ru_task:正在执行的任务信息
act_hi_taskinst:已经执行完的历史任务信息
Activiti学习记录(二)的更多相关文章
- Material Calendar View 学习记录(二)
Material Calendar View 学习记录(二) github link: material-calendarview; 在学习记录一中简单翻译了该开源项目的README.md文档.接下来 ...
- Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客
==他的博客应该不错,没有细看 Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客 http://blog.csdn.net/u012706811/article/det ...
- JavaScript学习记录二
title: JavaScript学习记录二 toc: true date: 2018-09-13 10:14:53 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...
- 2.VUE前端框架学习记录二
VUE前端框架学习记录二:Vue核心基础2(完结)文字信息没办法描述清楚,主要看编码实战里面,有附带有一个完整可用的Html页面,有需要的同学到脑图里面自取.脑图地址http://naotu.baid ...
- 【Activiti学习之二】Activiti API(一)
环境 JDK 1.8 MySQL 5.6 Tomcat 7 Eclipse-Luna activiti 6.0 一.Activiti数据查询准备数据: package com.wjy.act; imp ...
- Activiti学习(二)数据表结构
Activiti工作流引擎数据库表结构 数据库表的命名 Acitiviti数据库中表的命名都是以ACT_开头的.第二部分是一个两个字符用例表的标识.此用例大体与服务API是匹配的. l ...
- Spring Boot学习记录(二)–thymeleaf模板
自从来公司后都没用过jsp当界面渲染了,因为前后端分离不是很好,反而模板引擎用的比较多,thymeleaf最大的优势后缀为html,就是只需要浏览器就可以展现页面了,还有就是thymeleaf可以很好 ...
- 【java并发编程艺术学习】(四)第二章 java并发机制的底层实现原理 学习记录(二) synchronized
章节介绍 本章节主要学习 Java SE 1.6 中为了减少获得锁 和 释放锁 时带来的性能消耗 而引入的偏向锁 和 轻量级锁,以及锁的存储结构 和 升级过程. synchronized实现同步的基础 ...
- SpringBoot学习记录(二)
一. SpringBoot日志框架 SpringBoot:底层是Spring框架,Spring框架默认是用JCL(commons-logging): SpringBoot选用SLF4j和logback ...
随机推荐
- 帝都Day4(2)——数据结构
黄姓dalao is coming! 一.栈: 基本常识略. 例题:铁轨 模拟,O(n), Usaco2006 Nov 题目略 做法:单调栈(续命栈?) n//数量 a[]//奶牛 for(int i ...
- Java基础--正则表达式的规则
注意:正则表达式只关注格式是否正确,不关注内容是否有效. 一.字符集合, []表示一个字符. 1.[abc] :指a,b,c中的任意一个字符. 2.[^abc]:指除了a,b,c外的任意字符. 3.[ ...
- web综合案例03
web综合案例03 web综合案例03 web综合案例03 web综合案例03 ... 待复习
- 禁止tableview 像上滑动
tableView有一个bounces属性.默认YES,所以tableView上下用力拉都会有弹性滑动,如下设置可以禁止,但是这样的话上下弹性都没了 而经常的需求是上方不要弹性,下方要弹性,可以用监听 ...
- event对象的使用注意事项
首先event是在事件发生的时候产生的,所以必须在事件发生的事件监听函数里面使用他.不然的话就没用的.会找不到这个事件: 错误的写法: 报错的内容: 正确的写法:
- Eclipse与异常处理
快捷键:Ctrl+d删除光标所在的这一行 Alt+/ 智能提示 异常处理 异常是阻止当前方法或作用域继续执行的问题,在程序中导致程序中断运行的一些指令. try与catch关键字 try{ //有可能 ...
- (转)rename命令详解
rename命令详解: 原文:http://www.cnblogs.com/amosli/p/3491649.html 对文件重命名是常用的操作之一,一般对单个文件的重命名用mv命令,如: amosl ...
- (转)Mysql数据库之Binlog日志使用总结Linux下用户组、文件权限详解
Linux下用户组.文件权限详解 原文:http://blog.csdn.net/sdulibh/article/details/51566772 用户组 在linux中的每个用户必须属于一个组,不能 ...
- 深入理解C#中的IDisposable接口(转)
转自:https://www.cnblogs.com/wyt007/p/9304564.html 写在前面 在开始之前,我们需要明确什么是C#(或者说.NET)中的资源,打码的时候我们经常说释放资源, ...
- Spring事务管理的注解方式
使用注解实现Spring的声明式事务管理,更加简单! 步骤: 1) 必须引入Aop相关的jar文件 2) bean.xml中指定注解方式实现声明式事务管理以及应用的事务管理器类 3)在需要添加事务控制 ...