将带有类似审批的环节,控制审批做自动化处理
工作流的目标:减小业务与审批的耦合关系。当业务逻辑复杂的时候不同的角色权限又不同的审批流程。未使用工作流的业务,审批流程耦合是非常高的
二、BPMN-建模语言定义业务流程模型和符号
三、activiti 使用步骤1.部署activiti
- 获取jar包
2.流程定义
- 使用建模工具定义流程(.bpmn文件)
3.流程部署
- 将定义好的流程内容,存储到数据库
4.流程实例
- 流程实例:processInstance
- 通俗来讲,也就是申请人发的一次起流程实例(this),比如张三发起的请假、李四发起的出差。各自都是流程实例。
5.待办任务(Task)
- 用户可以查询当前流程的具体信息,具体任务等,使用接口获取,不用自己去数据库查找
6.处理任务
- 通过activiti处理审批流程
- jdk 1.8及以上
- Mysql 5.0 及以上
- Tomcat 8.5 及以上
*[activiti流程定义工具插件在IDEA和Eclipse上都可以运行]
五、activiti 数据库支持数据库版本
需要在数据库使用25张表
数据库 | 版本 |
---|---|
h2 | 1.3.168 |
mysql | 5.1.21 |
oracle | 12.2.0.1.0 |
postgres | 8.1 |
db2 | DB2 10.1 |
mssql | 2008 using sqljdbc4 |
配置activit的日志信息
log4j配置-非必要配置
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r[%15.15t] %-5p %30.30c %x -
%m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
#指定文件存放位置
log4j.appender.LOGFILE.File=D:\act\activiti.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r[%15.15t] %-5p %30.30c %x -%m\n
注意事项
activiti 配置分为两只配
- 默认配置方式–需要在resources文件夹下创建activiti.cfg.xml文件。源码固定了到此目录读取此文件
- [听说activiti7已支持写入springboot的配置,也就是在application.yml中配置,此处我没有试过]
6.1.1-默认配置使用默认配置
-
配置文件名固定为:activiti.cfg.xml
-
配置文件中bean对象也需要固定id和class
-
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"/>
-
-
Java中使用ProcessEngines创建生成表,或者调用servcie等等
-
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
-
activiti.cfg.xml配置
<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="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://121.89.222.205:3306/activiti7?characterEncoding=UTF-8&nullCatalogMeansCurrent=true&useSSL=false" />
<property name="jdbcUsername" value="root"/>
<property name="jdbcPassword" value="wuhong"/>
<property name="databaseSchemaUpdate" value="true"/>
bean>
beans>
配置好xml之后,直接调用getDefaultProcessEngine(),调用默认设置在数据库中生成表
/*
* 使用 Activiti的默认方式创建数据库表
*/
@Test
public void createDBTable(){
/*
1.使用Activiti的工具类,ProcessEngines.getDefaultProcessEngine() -- .getDefault默认方法,使用默认配置,读取默认的固定配置文件 "activiti.cfg.xml"
2.此方法会在数据库中创建 activiti的表
*/
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
6.1.2-一般配置一般配置
-
配置文件名字可以自定义,可以通过java对象指定文件名字读取
-
通过流程引擎配置类ProcessEngineConfiguration启
-
ProcessEngineConfiguration processEngineConfiguration2 = ProcessEngineConfiguration //读取配置文件名 .createProcessEngineConfigurationFromResource("activiti.cfg.xml"); ProcessEngineConfiguration processEngineConfiguration2 = ProcessEngineConfiguration //读取配置文件名,读取xml中配置类配置的bean-id,或者 bean-name .createProcessEngineConfiidgurationFromResource("activiti.cfg.xml","processEngineConfiguration");
-
自定义的activit配置文件
<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.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://121.89.222.205:3306/activiti7?characterEncoding=UTF-8&nullCatalogMeansCurrent=true&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="wuhong"/>
<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 name="databaseSchemaUpdate" value="true"/>
bean>
beans>
七、activiti 表结构
- activiti运行中需要用到25张表
表结构
- ACT_GE: = general 表示通用,普通的数据。各种情况都需要用到
- ACT_HI: = history 表示历史记录的表
- ACT_RE: = Repository(仓库),这些表中保存一些‘静态’信息,如流程定义和流程资源(如图片、规则等)
- ACT_RU: = runtime 运行是需要用到的表
表分类 | 表名 | 解释 |
---|---|---|
一般数据 | ||
[ACT_GE_BYTEARRAY] | 通用的流程定义和流程资源 | |
[ACT_GE_PROPERTY] | 系统相关属性 | |
流程历史记录 | ||
[ACT_HI_ACTINST] | 历史的流程实例 | |
[ACT_HI_ATTACHMENT] | 历史的流程附件 | |
[ACT_HI_COMMENT] | 历史的说明性信息 | |
[ACT_HI_DETAIL] | 历史的流程运行中的细节信息 | |
[ACT_HI_IDENTITYLINK] | 历史的流程运行过程中用户关系 | |
[ACT_HI_PROCINST] | 历史的流程实例 | |
[ACT_HI_TASKINST] | 历史的任务实例 | |
[ACT_HI_VARINST] | 历史的流程运行中的变量信息 | |
流程定义表 | ||
[ACT_RE_DEPLOYMENT] | 部署单元信息 | |
[ACT_RE_MODEL] | 模型信息 | |
[ACT_RE_PROCDEF] | 已部署的流程实例 | |
运行实例表 | ||
[ACT_RU_EVENT_SUBSCR] | 运行时事件 | |
[ACT_RU_EXECUTION] | 运行时流程执行实例 | |
[ACT_RU_IDENTITYLINK] | 运行时用户关系信息,存储任务节点与参与者的相关信息 | |
[ACT_RU_JOB] | 运行时作业 | |
[ACT_RU_TASK] | 运行时任务 | |
[ACT_RU_VARIABLE] | 运行时变量表 |
- processEngineConfiguration对象获取配置信息
- processEngineConfiguration对象可以得到ProcessEngine
- ProcessEngine可以获取各种Activiti *** 作DAO的service
- 例如RepositoryService可以 *** 作和 act_re***相关的表,处理和部署有关的工作流业务
- 例如RuntimeService就可以 *** 作和运行时的一些工作流业务信息
- 其他service作用类似
service名称 | service作用 |
---|---|
RepositoryService | activiti的资源管理类 |
RuntimeService | activiti的流程运行管理类 |
TaskService | activiti的任务管理类 |
HistoryService | activiti的历史管理类 |
ManagerService | activiti的引擎管理类 |
- 使用工具或插件,画出BPMN建模语言的流程图
- 加载流程文件部署到数据库
- 可以导出流程图作为png的图片显示
插件下载
-
插件网站可以下载Activit BPMN visualizer
-
也安装camunda-modeler工具实现流程设计
-
链接: https://pan.baidu.com/s/12l6GylwK16iXlviCFid-OA 提取码: c36m
需要设置中加载工具,可参考网络搜索结果,
导出流程图
- 右键文件–>Digrames --> show XXX信息
注意:
使用camunda的流程设计器,设计activit的流程图的话,需要修改xml
- 流程图中设置assignee:负责人时,使用camunda使用uel表达式,设置为生成文件后直接部署,流程中,数据库表读取不到assigne。
- 数据库读不到你传入值
- 需要改xml文件
camunda头部信息改为一下设置
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
xmlns:activiti="http://activiti.org/bpmn"
id="sample-diagram"
targetNamespace="http://bpmn.io/schema/bpmn"
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
十、流程部署
将画好的流程图文件通过api部署
此处为原生部署方式:
- 将画好的流程图通过目录读取到数据库中
//1.获取配置类processEngineConfiguration
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("activiti.cfg.xml","processEngineConfiguration");
//2.获取配置类processEngine工作流引擎
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
//3.获取配资源部署类的相关service -[ Repository ]
RepositoryService repositoryService = processEngine.getRepositoryService();
//4.创建流程部署
DeploymentBuilder builder = repositoryService.createDeployment();
builder.name("出差申请流程");
builder.addClasspathResource("bpmn/evection.bpmn20.xml");
builder.addClasspathResource("bpmn/evection.png");
Deployment deployment = builder.deploy();
- 还可以将多个流程图打包为Zip文件,进行批量部署
/**
* 使用Zip打包 部署资源
* [之前单独添加的一个资源文件,现在将多个bpmn打包文件通过zip打包]
*/
@Test
public void deployProcessByZip(){
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
InputStream inputStream =this.
getClass(). //获取类的信息
getClassLoader(). //获取整个工程的信息
getResourceAsStream("bpmn/newAct.zip"); //读取打包了的文件
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
Deployment deploy = repositoryService.createDeployment()
.addZipInputStream(zipInputStream)
.deploy();
System.out.println("部署信息:"+deploy);
System.out.println("流程name:"+deploy.getName());
// 部署信息:DeploymentEntity[id=1, name=null]
// 流程name:null
}
十一、流程下载
- 流程资源部署后,在数据库中以**BLOB(longblob)**二进制方式存储
- 下载流程可以通过repositoryService实现、或者是自定义 *** 作表的下载
一、使用Activiti服务下载
- 通过repositoryService服务实现下载
- IOUtils是来着 commons-io的包
/**
* 下载资源文件
*/
@Test
public void downRepository() throws Exception {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
ProcessDefinition evection = repositoryService.createProcessDefinitionQuery().processDefinitionKey("evection").singleResult();
String deploymentId = evection.getDeploymentId();
String diagramImageName = evection.getDiagramResourceName();
String resourceName = evection.getResourceName();
InputStream inIoImage =repositoryService.getResourceAsStream(deploymentId, diagramImageName);
InputStream inIoBPMN = repositoryService.getResourceAsStream(deploymentId, resourceName);
FileOutputStream fileBpmn = new FileOutputStream(new File("D:\IDEA-workspace\private\Learning_test\Activti7\evection.bpmn"));
FileOutputStream filePng = new FileOutputStream(new File("D:\IDEA-workspace\private\Learning_test\Activti7\evection.png"));
IOUtils.copy(inIoImage, filePng);
IOUtils.copy(inIoBPMN, fileBpmn);
inIoBPMN.close();
inIoImage.close();
fileBpmn.close();
filePng.close();
}
二、通过 *** 作表,自定义实现下载
- 需要读取数据库中的byte字节数据,实现数据转换、文件下载
public class ActivitiDemo {
//测试部署
@Test
public void testDeeploment() {
//1.获取配置类processEngineConfiguration
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("activiti.cfg.xml", "processEngineConfiguration");
//2.获取配置类processEngine工作流引擎
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
//3.获取配资源部署类的相关service -[ Repository ]
RepositoryService repositoryService = processEngine.getRepositoryService();
//4.创建流程部署
DeploymentBuilder builder = repositoryService.createDeployment();
builder.name("出差申请流程");
builder.addClasspathResource("bpmn/evection.bpmn20.xml");
builder.addClasspathResource("bpmn/evection.png");
Deployment deployment = builder.deploy();
System.out.println("流程部署id=" + deployment.getId());
System.out.println("流程部署name=" + deployment.getName());
}
/**
* 开启流程:
*/
@Test
public void testRuntimeDemo() {
//采用默认方式获取工作流引擎
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();
ProcessInstance evection = runtimeService.startProcessInstanceByKey("evection");
System.out.println("流程定义ID=" + evection.getProcessDefinitionId());
System.out.println("流程实例ID=" + evection.getId());
System.out.println("当前活动ID=" + evection.getActivityId());
}
/**
* 查询个人待执行的任务
*/
@Test
public void testFindPersonalTaskList() {
//1.获取引擎
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
//2.获取taskService
TaskService taskService = defaultProcessEngine.getTaskService();
//3.根据key查询任务
List<Task> list = taskService.
createTaskQuery().//创建查询
processDefinitionKey("evection").//流程实例的key
taskAssignee("张三").//要查询的负责人
list();
for (Task task : list) {
System.out.println("实例-id" + task.getProcessInstanceId());
System.out.println("任务-id" + task.getId());
System.out.println("任务当前负责人信息" + task.getAssignee());
System.out.println("任务名字" + task.getName());
}
}
/**
* 查询个人待执行的任务
*/
@Test
public void compeletTask() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = defaultProcessEngine.getTaskService();
taskService.complete("5005");
}
@Test
public void taskBy李四() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = defaultProcessEngine.getTaskService();
//获取李四对应的任务
Task task = taskService.createTaskQuery().processDefinitionKey("evection").taskAssignee("李四").singleResult();
System.out.println(task);
taskService.complete(task.getId());
}
@Test
public void taskBy王五() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = defaultProcessEngine.getTaskService();
//获取王五 对应的任务
Task task = taskService.createTaskQuery().processDefinitionKey("evection").taskAssignee("王五").singleResult();
System.out.println(task);
taskService.complete(task.getId());
}
@Test
public void taskBy赵六() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = defaultProcessEngine.getTaskService();
//获取赵六 对应的任务
Task task = taskService.createTaskQuery().processDefinitionKey("evection").taskAssignee("赵六").singleResult();
System.out.println(task);
taskService.complete(task.getId());
}
}
十二、流程删除
- 使用repositoryService服务进行流程删除
- 删除流程需要删除re相关的表和通用表中的资源信息(act_ge_bytearray)
- 流程部署且被开启的情况下,需要强制删除部署的话,需要使用级联删除
/**
* 删除已经部署的流程
*/
@Test
public void deleteProcess(){
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
//通过部署id删除部署
repositoryService.deleteDeployment("1");
//使用True,开启级联删除
repositoryService.deleteDeployment("2501",true);
}
十三、流程启动
步骤解析
- 部署流程,BPMN流程图画好后传到数据库,存入到 act_re_procdef(流程部署实例表)
- 开始流程,调用RuntimeService开启流程,通过部署实例的信息,在数据库 *act_ru_ **开头的表中 *** 作任务(Task)的流程
- 结束流程,结束流程之后,与之相关runtime的表中的信息将会删除,完整的流程信息保存到Histroy表中
public class ActivitiDemo {
//测试部署
@Test
public void testDeeploment() {
//1.获取配置类processEngineConfiguration
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("activiti.cfg.xml", "processEngineConfiguration");
//2.获取配置类processEngine工作流引擎
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
//3.获取配资源部署类的相关service -[ Repository ]
RepositoryService repositoryService = processEngine.getRepositoryService();
//4.创建流程部署
DeploymentBuilder builder = repositoryService.createDeployment();
builder.name("出差申请流程");
builder.addClasspathResource("bpmn/evection.bpmn20.xml");
builder.addClasspathResource("bpmn/evection.png");
Deployment deployment = builder.deploy();
System.out.println("流程部署id=" + deployment.getId());
System.out.println("流程部署name=" + deployment.getName());
}
/**
* 开启流程:
*/
@Test
public void testRuntimeDemo() {
//采用默认方式获取工作流引擎
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();
ProcessInstance evection = runtimeService.startProcessInstanceByKey("evection");
System.out.println("流程定义ID=" + evection.getProcessDefinitionId());
System.out.println("流程实例ID=" + evection.getId());
System.out.println("当前活动ID=" + evection.getActivityId());
}
/**
* 查询个人待执行的任务
*/
@Test
public void testFindPersonalTaskList() {
//1.获取引擎
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
//2.获取taskService
TaskService taskService = defaultProcessEngine.getTaskService();
//3.根据key查询任务
List<Task> list = taskService.
createTaskQuery().//创建查询
processDefinitionKey("evection").//流程实例的key
taskAssignee("张三").//要查询的负责人
list();
for (Task task : list) {
System.out.println("实例-id" + task.getProcessInstanceId());
System.out.println("任务-id" + task.getId());
System.out.println("任务当前负责人信息" + task.getAssignee());
System.out.println("任务名字" + task.getName());
}
}
/**
* 查询个人待执行的任务
*/
@Test
public void compeletTask() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = defaultProcessEngine.getTaskService();
taskService.complete("5005");
}
@Test
public void taskBy李四() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = defaultProcessEngine.getTaskService();
//获取李四对应的任务
Task task = taskService.createTaskQuery().processDefinitionKey("evection").taskAssignee("李四").singleResult();
System.out.println(task);
taskService.complete(task.getId());
}
@Test
public void taskBy王五() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = defaultProcessEngine.getTaskService();
//获取王五 对应的任务
Task task = taskService.createTaskQuery().processDefinitionKey("evection").taskAssignee("王五").singleResult();
System.out.println(task);
taskService.complete(task.getId());
}
@Test
public void taskBy赵六() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = defaultProcessEngine.getTaskService();
//获取赵六 对应的任务
Task task = taskService.createTaskQuery().processDefinitionKey("evection").taskAssignee("赵六").singleResult();
System.out.println(task);
taskService.complete(task.getId());
}
}
十四、流程与业务关联
实现步骤
Activiti流程运行时 *** 作的都是数据库中 Runtime相关的表,实现思想就是将业务逻辑中代笔审批一个key,加入到Activiti的表中
- act_ru_execution(运行流程实例表)中的 **BUSINESS_KEY_**字段,作为添加的业务字段
/*
1.添加业务中id到Activiti的表中
*/
@Test
public void test1(){
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();
//参数1:流程实例key, 参数2:BusinessKey 代笔业务的id
//假设这里 “UUID1001”代表是一个人员发起的某种审批申请
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("evection", "UUID1001");
}
十五、流程挂起、激活
原因解释
为了应对不同的应用场景,类似于公司内部举行盘点、月末最后一天不接收审批等特殊场景下,工作流存在挂起、激活的转台,表示此时的流程状态为特殊状态,不能继续往下处理流程
- 注意区别单个流程挂起和多个流程挂起的区别
*** 作代码
挂起、激活所有同类型的流程
/*
批量流程挂起、流程激活
*/
@Test
public void test2() {
/**
* 1.查询流程信息--当需要 *** 作多个运行中的流程实例时,从流程定义的id中获取信息,比一个一个的获取流程运行实例更高效
* 2.获取当前的信息是被挂起、或是激活转状态
* 3.根据业务需求对不同状态的流程做 *** 作
* 单词--Suspended:暂停、activate:激活
*/
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
//获取流程的查询对象
ProcessDefinition evection = repositoryService.createProcessDefinitionQuery().processDefinitionKey("evection").singleResult();
//是否是挂起状态
boolean suspended = evection.isSuspended();
//如果是挂起,就激活、否则就挂起
if (suspended) {
//激活 *** 作
//参数1:流程Id、参数2:是否激活、参数3:时间(可以传null)
repositoryService.activateProcessDefinitionById(evection.getId(), true, null);
} else {
//挂起 *** 作
//参数1:流程Id、参数2:是否挂起、参数3:时间(可以传null)
repositoryService.suspendProcessDefinitionById(evection.getId(), true, null);
}
}
挂起、激活某一单独的流程
/*
单个实例挂起、激活 *** 作
*/
@Test
public void test3() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();
//从数据库中取值的流程实例id -22501
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId("22501").singleResult();
System.out.println(processInstance.toString());
if (processInstance.isSuspended()){
runtimeService.activateProcessInstanceById("22501");
}else {
runtimeService.suspendProcessInstanceById("22501");
}
System.out.println(runtimeService.createProcessInstanceQuery().processInstanceId("22501").toString());
}
*** 作原理
- 调用暂停(挂起)、激活状态,需要传入流程实例id。可以是部署流程实例,可以挂起此流程(比如部署的请假流程)的所有运行流程实例(张三、李四的请假流程)都可以同时挂起。当然也可以通过具体的某流程挂起
- 数据库中,suspension_status字段。激活状态 suspension_status =1,暂停挂起状态==suspension_status=2==
- act_re_procedf:流程实例定义信息表中,有suspension_status字段。
- act_ru_execution:运行中流程实例表中,有suspension_status字段。
- act_ru_task:任务表中,有suspension_status字段。
2、BPMN-流程设计 一、BPMN-表达式
-
Activiti 使用 UEL 表达式UEL-value 和 UEL-method
-
**UEL叫做统一表达式语言,${}在括号可以填入变量、支持逻辑运行[ ==,!=]等 **
-
表达式支持解析基础类型、 bean、 list、 array 和 map,也可作为条件判断。如:${order.price > 100 && order.price < 250}
使用方式
在流程图设计中,可以使用表达式传入 Assignee(审核人UserTask信息)字段值,从此达到动态传值的目标,而不是写入固定的值
在项目中使用将表达式内容通过Map集合传入
/*
测试uel表达式
*/
@Test
public void test1(){
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();
Map<String,Object> assigneeMap = new HashMap<>();
assigneeMap.put("account1", "小李");
assigneeMap.put("account2", "张经理");
assigneeMap.put("account3", "赵总经理");
assigneeMap.put("account4", "财务审批");
runtimeService.startProcessInstanceByKey("newEvection",assigneeMap );
}
表达式是支持动态设置
- 流程图中设置好表达式逻辑
- 在程序中添加变量设置,以map方式添加表达式实例
- 可以在startProcess开启任务时、complete完成一个审批时、run运行时setVariable设置变量对象
Map<String, Object> map = new HashMap<>();
Student student = new Student();
student.setDays(5);
student.setName("张三");
map.put("student", student);
runtimeService.startProcessInstanceByKey("studentProcess", map);//启动时
taskService.complete(task.getId(),map);//完成其中一个审批时
runtimeService.setVariable(task.getId(),"student",map);//运行状态时
注意事项
由于使用了表达式分配,必须保证在任务执行过程表达式执行成功,比如:
某个任务使用了表达式${order.price > 100 && order.price < 250},当执行该任务时必须保证 order 在
流程变量中存在,否则 activiti 异常。
- 流程图中表达式变量名不存在会报错
- 流程图中表达式变量值为NULL,流程流程会结束
- 表达式都不符合条件,流程结束
- 表达式联系不设置条件,两个都走
-
使用监听器指定负责人,在流程设计中就不需要指定Assignee
-
监听器中可以设置事件(Event)、类型(Type)、类(class)等等属性
Event
表示触发事件
事件类型 | 事件含义 |
---|---|
Create | 任务创建后触发 |
Assignment | 任务分配后触发 |
Delete | 任务完成后触发 |
All | 所有事件发生都触发 |
complete | 任务完成后触发 |
update | 任务更新后触发 |
timeout | 任务超时后触发 |
设置好监听器的监听类型,在以上或如图的步骤时,会触发监听器
Type
触发的类型
我这里使用的camundar-modeler设计器
表示监听器的类型
class
class表示监听器实现类的地址:项目相对位置:*com.wuhong.listn.ActivitiListnener.写入到流程图中
public class ActivitiListnener implements TaskListener { //实现接口 - TaskListener
@Override
public void notify(DelegateTask delegateTask) {
String taskName = delegateTask.getName();//任务名字
String eventName = delegateTask.getEventName();//事件名字
//根据业务要求,实现监听需求
if (taskName.equals("经理审批") && "create".equals(eventName)) {
delegateTask.setAssignee("张三");
}
}
}
三、组任务
一个环节可以同时设置多个审批人
a、查询组任务
指定候选人,查询该候选人当前的待办任务。
候选人不能立即办理任务。
Task task = taskService.createTaskQuery().processDefinitionKey("studentProcess4").taskCandidateUser("王五").singleResult();
b、拾取(claim)任务
该组任务的所有候选人都能拾取。
将候选人的组任务,变成个人任务。原来候选人就变成了该任务的负责人。
如果拾取后不想办理该任务?
//王五拾取任务
taskService.claim(task.getId(),"王五");
c、查询个人任务
查询方式同个人任务部分,根据assignee查询用户负责的个人任务。
拾取前
拾取后
d、办理个人任务
拾取后做相关的流程 *** 作
e、归还个人任务
//组任务--归还任务
@Test
public void test10() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = defaultProcessEngine.getTaskService();
//候选人拾取后已经变成负责人了,所以要用taskAssignee 去查
Task task = taskService.createTaskQuery().processDefinitionKey("studentProcess4").taskAssignee("王五").singleResult();
//归还任务
taskService.unclaim(task.getId());
}
四、BPMN-网关
排他网关ExclusiveGateway
- 注意:排他网关只会选择一个为true的分支执行。如果有两个分支条件都为true,排他网关会选择id值较小的一条分支去执行。
并行网关ParallelGateway
- 会签
网关必须一前一后,经前面的网关进入后,所有的UsertTask执行任务,才会汇聚到右边的网关
l fork分支:
并行后的所有外出顺序流,为每个顺序流都创建一个并发分支。
l join汇聚:
所有到达并行网关,在此等待的进入分支, 直到所有进入顺序流的分支都到达以后, 流程就会通过汇聚网关。
包含网关InclusiveGateway
可以认为是排他网关和并行网关的结合
事件网关EventGateway
bibil黑马的视频学习这里居然没有了,就懒得看了。看整合的话可以搜一下别人的解决方案,黑马的整合包含了SpringSecurity的配置
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)