流程变更的时候不需要改变源代码,因为节点的数据是记录在表中的,而对于多一个流程或者少一个流程来说,只是在表中多一条记录或者少一条记录而已,并不需要去改变源代码.
1、画好流程图
2、将流程图的每个节点的数据读取并放入数据库
3、从表中读取第一条记录,处理并删除
BPM(Business Process Management),即业务流程管理,是一种以规范化的构造端到端的卓越
业务流程为中心,以持续的提高组织业务绩效为目的系统化方法,常见商业管理教育如EMBA、MBA
等均将 BPM 包含在内。
BPMN(Business Process Model And Notation)- 业务流程模型和符号 是由 BPMI(Business
Process Management Initiative)开发的一套标准的业务流程建模符号,使用 BPMN 提供的符号可以
创建业务流程。
idea安装actiBPM插件
CREATE DATABASE activiti DEFAULT CHARACTER SET utf8;
<properties>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
</properties>
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-model</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-converter</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-json-converter</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-layout</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti.cloud</groupId>
<artifactId>activiti-cloud-services-api</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>alfresco</id>
<name>Activiti Releases</name>
<url>https://artifacts.alfresco.com/nexus/content/repositories/activiti-releases/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/contex http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/itcast0711activiti" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="maxActive" value="3" />
<property name="maxIdle" value="1" />
bean>
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="dataSource" ref="dataSource">property>
<property name="databaseSchemaUpdate" value="true"/>
bean>
beans>
public static void main(String[] args) {
//创建ProcessEngineConfiguration
ProcessEngineConfiguration configuration =
ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
//通过ProcessEngineConfiguration创建ProcessEngine,此时会创建数据库
ProcessEngine processEngine =
configuration.buildProcessEngine();
System.out.println(processEngine);
}
ACT_RE_*: 'RE’表示 repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,
规则,等等)。
ACT_RU_*: 'RU’表示 runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,
等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删
除这些记录。 这样运行时表可以一直很小速度很快。
ACT_HI_*: 'HI’表示 history。 这些表包含历史数据,比如历史流程实例, 变量,任务等
等。
AC T_GE_*: GE表示 general。通用数据, 用于不同场景下。
工作流引擎,相当于一个门面接口,通过 ProcessEngineConfiguration 创建 processEngine,通过
ProcessEngine 创建各个 service 接口。
一般创建方式:
//通过ProcessEngineConfiguration创建ProcessEngine
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
简单创建方式:
将 activiti.cfg.xml文件名及路径固定,且 activiti.cfg.xml文件中有 processEngineConfiguration 的配置,
可以使用如下代码创建 processEngine:
//使用classpath下的activiti.cfg.xml中的配置创建processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
System.out.println(processEngine);
Service 创建方式
通过 ProcessEngine 创建 Service,Service 是工作流引擎提供用于进行工作流部署、执行、管理的服
务接口。
方式如下
RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
……
Service 总览
RepositoryService
是 activiti的资源管理类,提供了管理和控制流程发布包和流程定义的操作。使用工作流建模工
具设计的业务流程图需要使用此 service 将流程定义文件的内容部署到计算机。
除了部署流程定义以外还可以:
查询引擎中的发布包和流程定义。
暂停或激活发布包,对应全部和特定流程定义。 暂停意味着它们不能再执行任何操作了,激活
是对应的反向操作。
获得多种资源,像是包含在发布包里的文件, 或引擎自动生成的流程图。
获得流程定义的 pojo 版本, 可以用来通过 java 解析流程,而不必通过 xml。
RuntimeService
它是 activiti的流程运行管理类。可以从这个服务类中获取很多关于流程执行相关的信息
TaskService
是 activiti的任务管理类。可以从这个类中获取任务的信息。
HistoryService
是 activiti 的历史管理类,可以查询历史信息,执行流程时,引擎会保存很多数据(根据配置),比
如流程实例启动时间,任务的参与者, 完成任务的时间,每个流程实例的执行路径,等等。 这个
服务主要通过查询功能来获得这些数据。
如果有中文乱码问题,参考文章:https://blog.csdn.net/vimonkey/article/details/72910153
先备份一份文件,再改名:
holidy.bpmn -> holidy.xml
public class ActivitiDeployment {
public static void main(String[] args) {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取repositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
//部署对象
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("diagram/holidy.bpmn")// bpmn文件
.addClasspathResource("diagram/holidy.png")// 图 片 文 件
.name("请假申请流程")
.deploy();
System.out.println("流程部署id:" + deployment.getId());
System.out.println("流程部署名称:" + deployment.getName());
}
}
影响的表:
act_re_deployment 部署信息
act_re_procdef 流程定义的一些信息
act_ge_bytearray 流程定义的bpmn文件及png文件
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RunService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
//3.创建流程实例 流程定义的key需要知道 holiday
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess_1");
//4.输出实例的相关信息
System.out.println("流程部署ID"+processInstance.getDeploymentId());//null
System.out.println("流程定义ID"+processInstance.getProcessDefinitionId());//holiday:1:4
System.out.println("流程实例ID"+processInstance.getId());//2501
System.out.println("活动ID"+processInstance.getActivityId());//null
}
key在这里可以找到:
也可以在bpmn文件中找到。
影响的表:
act_hi_actinst 已完成的活动信息
act_hi_identitylink 参与者信息
act_hi_procinst 流程实例
act_hi_taskinst 任务实例
act_ru_execution 执行表
act_ru_identitylink 参与者信息
act_ru_task 任务
public class ActivitiTaskQuery {
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService对象
TaskService taskService = processEngine.getTaskService();
//3.根据流程定义的key,负责人assignee来实现当前用户的任务列表查询
Task task = taskService.createTaskQuery()
.processDefinitionKey("myProcess_1")
.taskAssignee("zhangsan")
.singleResult();
//4.任务列表的展示
System.out.println("流程实例ID:"+task.getProcessInstanceId());
System.out.println("任务ID:"+task.getId()); //5002
System.out.println("任务负责人:"+task.getAssignee());
System.out.println("任务名称:"+task.getName());
}
}
public class ActivitiCompleteTask {
//查询当前用户wangwu的任务并处理掉
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService对象
TaskService taskService = processEngine.getTaskService();
//3.查询当前用户的任务
Task task = taskService.createTaskQuery()
.processDefinitionKey("myProcess_1")
.taskAssignee("zhangsan")
.singleResult();
//4.处理任务,结合当前用户任务列表的查询操作的话,任务ID:task.getId()
taskService.complete(task.getId());
//5.输出任务的id
System.out.println(task.getId());
}
//lishi完成自己的任务
/*public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService对象
TaskService taskService = processEngine.getTaskService();
//3.处理任务,结合当前用户任务列表的查询操作的话,任务ID:5002
taskService.complete("5002");
}*/
//zhangsan完成自己的任务
/*public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService对象
TaskService taskService = processEngine.getTaskService();
//3.处理任务,结合当前用户任务列表的查询操作的话,任务ID:2505
taskService.complete("2505");
}*/
影响的表:
act_hi_actinst
act_hi_identitylink
act_hi_taskinst
act_ru_identitylink
act_ru_task
将 holiday .bpmn 和 holiday .png 压缩成 zip 包。
public void deployProcessByZip() {
// 定义zip输入流
InputStream inputStream = this
.getClass()
.getClassLoader()
.getResourceAsStream(
" diagram/holiday.zip");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
// 获取repositoryService
RepositoryService repositoryService = processEngine
.getRepositoryService();
// 流程部署
Deployment deployment = repositoryService.createDeployment()//
.addZipInputStream(zipInputStream)
.deploy();
System.out.println("流程部署id:" + deployment.getId());
System.out.println("流程部署名称:" + deployment.getName());
}
public class QueryProcessDefinition {
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.创建RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.得到ProcessDefinitionQuery对象,可以认为它就是一个查询器
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
//4.设置条件,并查询出当前的所有流程定义 查询条件:流程定义的key=holiday
//orderByProcessDefinitionVersion() 设置排序方式,根据流程定义的版本号进行排序
List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey("holiday")
.orderByProcessDefinitionVersion()
.desc().list();
//5.输出流程定义信息
for(ProcessDefinition processDefinition :list){
System.out.println("流程定义ID:"+processDefinition.getId());
System.out.println("流程定义名称:"+processDefinition.getName());
System.out.println("流程定义的Key:"+processDefinition.getKey());
System.out.println("流程定义的版本号:"+processDefinition.getVersion());
System.out.println("流程部署的ID:"+processDefinition.getDeploymentId());
}
}
}
public class DeleteProcessDefinition {
/**
* 注意事项:
* 1.当我们正在执行的这一套流程没有完全审批结束的时候,此时如果要删除流程定义信息就会失败
* 2.如果公司层面要强制删除,可以使用repositoryService.deleteDeployment("1",true);
* //参数true代表级联删除,此时就会先删除没有完成的流程结点,最后就可以删除流程定义信息 false的值代表不级联
*
* @param args
*/
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.创建RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.执行删除流程定义 参数代表流程部署的id
repositoryService.deleteDeployment("1");
}
}
影响的表:
act_ge_bytearray
act_re_deployment
act_re_procdef
注意事项:
* 注意事项:
* 1.当我们正在执行的这一套流程没有完全审批结束的时候,此时如果要删除流程定义信息就会失败
* 2.如果公司层面要强制删除,可以使用repositoryService.deleteDeployment("1",true);
* //参数true代表级联删除,此时就会先删除没有完成的流程结点,最后就可以删除流程定义信息 false的值代表不级联
<dependency>
<groupId>commons-iogroupId>
<artifactId>commons-ioartifactId>
<version>2.0version>
dependency>
/**
* 需求:
* 1.从Activiti的act_ge_bytearray表中读取两个资源文件
* 2.将两个资源文件保存到路径: G:\Activiti7开发计划\Activiti7-day03\资料
*
* 技术方案:
* 1.第一种方式使用actviti的api来实现
* 2.第二种方式:其实就是原理层面,可以使用jdbc的对blob类型,clob类型数据的读取,并保存
* IO流转换,最好commons-io.jar包可以轻松解决IO操作
*
* 真实应用场景:用户想查看这个请假流程具体有哪些步骤要走?
*
*
*/
public static void main(String[] args) throws IOException {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.得到查询器:ProcessDefinitionQuery对象
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
//4.设置查询条件
processDefinitionQuery.processDefinitionKey("holiday");//参数是流程定义的key
//5.执行查询操作,查询出想要的流程定义
ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
//6.通过流程定义信息,得到部署ID
String deploymentId = processDefinition.getDeploymentId();
//7.通过repositoryService的方法,实现读取图片信息及bpmn文件信息(输入流)
//getResourceAsStream()方法的参数说明:第一个参数部署id,第二个参数代表资源名称
//processDefinition.getDiagramResourceName() 代表获取png图片资源的名称
//processDefinition.getResourceName()代表获取bpmn文件的名称
InputStream pngIs = repositoryService
.getResourceAsStream(deploymentId,processDefinition.getDiagramResourceName());
InputStream bpmnIs = repositoryService
.getResourceAsStream(deploymentId,processDefinition.getResourceName());
//8.构建出OutputStream流
OutputStream pngOs =
new FileOutputStream("G:\\Activiti7开发计划\\Activiti7-day03\\资料\\"+processDefinition.getDiagramResourceName());
OutputStream bpmnOs =
new FileOutputStream("G:\\Activiti7开发计划\\Activiti7-day03\\资料\\"+processDefinition.getResourceName());
//9.输入流,输出流的转换 commons-io-xx.jar中的方法
IOUtils.copy(pngIs,pngOs);
IOUtils.copy(bpmnIs,bpmnOs);
//10.关闭流
pngOs.close();
bpmnOs.close();
pngIs.close();
bpmnIs.close();
}
public class HistoryQuery {
public static void main(String[] args) throws IOException {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到HistoryService
HistoryService historyService = processEngine.getHistoryService();
//3.得到HistoricActivitiInstanceQuery对象
HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
historicActivityInstanceQuery.processInstanceId("2501");//设置流程实例的id
//4.执行查询
List<HistoricActivityInstance> list = historicActivityInstanceQuery
.orderByHistoricActivityInstanceStartTime().asc().list();//排序StartTime
//5.遍历查询结果
for (HistoricActivityInstance instance :list){
System.out.println(instance.getActivityId());
System.out.println(instance.getActivityName());
System.out.println(instance.getProcessDefinitionId());
System.out.println(instance.getProcessInstanceId());
System.out.println("=============================");
}
}
}
启动流程实例的时候,关联业务标识businessKey
/**
* 启动流程实例,添加进businessKey
*
* 本质:act_ru_execution表中的businessKey的字段要存入业务标识
*/
public class BusinessKeyAdd {
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RuntimeService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
//3.启动流程实例,同时还要指定业务标识businessKey 它本身就是请假单的id
//第一个参数:是指流程定义key
//第二个参数:业务标识businessKey
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday", "1001");
//4.输出processInstance相关的属性,取出businessKey使用:processInstance.getBusinessKey()
System.out.println(processInstance.getBusinessKey());
}
}
public class SuspendProcessInstance {
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.查询流程定义的对象
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("holiday").singleResult();
//4.得到当前流程定义的实例是否都为暂停状态
boolean suspended = processDefinition.isSuspended();
String processDefinitionId = processDefinition.getId();
//5.判断
if(suspended){
//说明是暂停,就可以激活操作
repositoryService.activateProcessDefinitionById(processDefinitionId,true
,null);
System.out.println("流程定义:"+processDefinitionId+"激活");
}else{
repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
System.out.println("流程定义:"+processDefinitionId+"挂起");
}
}
}
public class SuspendProcessInstance2 {
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
//3.查询流程实例对象
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId("2501").singleResult();
//4.得到当前流程定义的实例是否都为暂停状态
boolean suspended = processInstance.isSuspended();
String processInstanceId = processInstance.getId();
//5.判断
if(suspended){
//说明是暂停,就可以激活操作
runtimeService.activateProcessInstanceById(processInstanceId);
System.out.println("流程:"+processInstanceId+"激活");
}else{
runtimeService.suspendProcessInstanceById(processInstanceId);
System.out.println("流程定义:"+processInstanceId+"挂起");
}
}
}