Activiti工作流基础

一、activiti配置文件


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?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">
<!-- spring模式加载的class不同 -->
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">

<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db_activiti" />
<!-- 数据库配置也可以直接用数据源dataSource注入 -->
<property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
<property name="jdbcUsername" value="root" />
<property name="jdbcPassword" value="root" />
<!-- false:关闭;true:当表不存在时自动创建;create-drop/drop-create -->
<property name="databaseSchemaUpdate" value="true" />
<!-- 监控流程作业,默认false -->
<property name="jobExecutorActivate" value="false" />
<!--
none: 跳过所有的历史数据。性能最优,但是没有历史数据。
activity: 保存所有的流程实例和活动信息。只保留最后信息,没有明细信息。
audit: 默认级别。保存所有的流程实例,任务、活动、表单属性等信息。
full: 最高级别,最完整的的历史信息。除了audit中的信息外,还包含详细信息。
-->
<property name="history" value="audit" />
<!-- 打开异步处理Service任务 -->
<property name="asyncExecutorActivate" value="true"></property>
<!-- 发布流程不生成流程图 -->
<property name="createDiagramOnDeploy" value="false" />
<!-- 字体 -->
<property name="activityFontName" value="宋体" />
<property name="labelFontName" value="宋体" />
<!-- 不保存流程图片 -->
<property name="createDiagramOnDeploy" value="false" />

<property name="DbIdentityUsed" value="true" />
<property name="DbHistoryUsed" value="true" />
<property name="databaseTablePrefix" value="T_" />
<property name="databaseType" value="mysql" />
</bean>

</beans>

二、数据库表

参考:Activiti数据库表结构(表详细版)

activiti6.0新增:

  • ACT_RU_TIMER_JOB 存放定时任务
  • ACT_RU_SUSPENDED_JOB 存放暂停任务
  • ACT_RU_DEADLETTER_JOB 无法执行的任务
  • ACT_EVT_LOG 异步日志表
  • ACT_PROCDEF_INFO 流程定义扩展表

三、service接口

  • RepositoryService

    流程仓库Service,用于管理流程仓库,如部署、删除、读取流程资源。

  • IdentifyService

    身份Service,管理和查询用户、组之间的关系。

  • RuntimeService

    运行时Service,管理所有正在运行状态的流程实例、任务等。

  • TaskService

    任务Service,用于管理、查询任务,如签收、办理、指派等。

  • FormService

    表单Service,用于读取和流程、任务相关的表单数据。

  • HistoryService

    历史Service,可以查询所有历史数据。

  • ManagementService

    引擎管理Service,和具体业务无关,主要是可以查询引擎配置、数据库、作业等。

7个service都是通过ProcessEngine对象来获取的

ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();

四、activiti流程设计器使用(BPMN2.0规范)

事件

1、事件的分类与定义

  • 定时器事件定义

    可以用在开始事件、中间事件、边界事件。可选指定时间触发、循环触发。支持cron表达式

  • 错误事件定义

    可以用在开始事件、结束事件、边界事件。捕获/抛出错误。

  • 信号事件定义

    通过一个信号控制多个流程实例,可以用在边界事件、中间事件。

  • 消息事件定义

    一个消息控制一个流程实例

  • 取消事件定义

    用在事务子流程模型中,有取消边界事件和取消结束事件

  • 补偿事件定义

    补偿事件

  • 其他事件

2、开始事件

  • 无指定开始事件
  • 定时器开始事件

    必须在配置文件打开异步处理Service任务,可以设置定时器触发方式

  • 消息开始事件

    通过消息名称启动流程:
    ProcessInstance pi = runService.startProcessInstanceByMessage(“msgName”);
    流程配置文件添加<message id="msgA" name="msgName"></message>

  • 错误开始事件

    流程中抛出异常,在事件子流程开始错误事件中捕获异常
    流程配置文件添加<error id="countError" errorCode="abc"></error>
    处理类抛出throw new org.activiti.engine.delegate.BpmnError("abc");

3、结束事件

  • 无指定结束事件

  • 错误结束事件

    流程以错误事件结束,然后事务子流程中就会捕获,从而执行子流程。或者触发边界错误捕获流程。

  • 取消结束事件

    在事务子流程中,触发取消结束事件后,就会触发所有补偿边界事件,然后先执行补偿边界事件,再判断整个事务子流程中是否有边界事件,有就执行事务子流程中的。

    1
    2
    3
    4
    <endEvent id="cancelendevent1" name="CancelEnd">
    <cancelEventDefinition></cancelEventDefinition>
    </endEvent>
    >
  • 终止结束事件

    当一个流程实例中,有多个任务都可以执行(并行网关),有一条执行到了终止结束事件,那么整个流程实例都终止了。

4、边界事件

  • 定时器边界事件

    当触发定时器时,执行定时器指定的任务

  • 错误边界事件

    捕获异常:throw new org.activiti.engine.delegate.BpmnError("abc");

  • 信号边界事件

    ,当执行到某个节点的时候触发信号或者消息时,执行另一个任务。申请–>审批–>审批不通过触发事件–>回到申请

  • 取消边界事件

    当事务子流程中,取消结束事件被触发后,补偿边界事件触发,然后子流程取消边界事件也会触发

  • 补偿边界事件

    1
    2
    3
    4
    <boundaryEvent id="boundarycompensation1" name="Compensate" attachedToRef="usertask1" cancelActivity="true">
    <compensateEventDefinition></compensateEventDefinition>
    </boundaryEvent>
    >

5、中间事件

  • 定时器中间事件(捕获)

    必须等待定时器触发后才能执行后面的节点任务(下个节点延迟拿到执行)

    1
    2
    3
    4
    5
    6
    <intermediateCatchEvent id="timerintermediatecatchevent1"
    name="TimerCatchEvent">
    <timerEventDefinition>
    <timeDuration>PT5S</timeDuration>
    </timerEventDefinition>
    </intermediateCatchEvent>

>

  • 信号中间事件(捕获和抛出)

    比如并行网关里,多条执行任务都是捕获信号中间事件,然后其中一条任务执行完成后,抛出信号中间事件,其他有捕获信号中间时间的执行任务才能往下走。(中间信号事件是自动触发的)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <signal id="finishPay" name="finishPay"></signal>
    <!-- 捕获 -->
    <intermediateThrowEvent id="signalintermediatethrowevent1" name="SignalThrowEvent">
    <signalEventDefinition signalRef="finishPay"></signalEventDefinition>
    </intermediateThrowEvent>
    <!-- 抛出 -->
    <intermediateCatchEvent id="signalintermediatecatchevent2"
    name="SignalCatchEvent">
    <signalEventDefinition signalRef="finishPay"></signalEventDefinition>
    </intermediateCatchEvent>
    >
  • 消息中间事件(捕获)

1
2
3
4
Execution run = runService.createExecutionQuery().messageEventSubscriptionName("message").singleResult();
System.out.println(run.getId());
runService.messageEventReceived("message", run.getId());
>
  • 信号中间事件
1
2
3
4
5
6
7
8
9
// 启动流程
ProcessInstance pi = runService.startProcessInstanceById(pd.getId());
// 查当前的子执行流(只有一个)
Execution exe = runService.createExecutionQuery()
.processInstanceId(pi.getId()).onlyChildExecutions()
.singleResult();
System.out.println(pi.getId() + ", 当前节点:" + exe.getActivityId());
runService.signalEventReceived("testSignal");
>
  • 补偿中间事件

6、补偿事件

补偿边界事件
  • 事务子流程有取消结束事件就会执行子流程中补偿边界事件
  • 触发补偿中间事件==>触发边界补偿事件
补偿中间事件

触发补偿中间事件就会触发所有之前任务的边界补偿事件

任务

1、用户任务

  • 分配任务的候选人

    • 方式1:使用taskService的addCandidateGroup和addCandidateUser方法
    • 方式2:使用XML配置
      id
      1
      2
      3
      4
      5
      6
      7
          <potentialOwner>
      <resourceAssignmentExpression>
      <formalExpression>user(angus), group(management), boss
      </formalExpression>
      </resourceAssignmentExpression>
      </potentialOwner>
      </userTask>
  • 分配任务代理人
    一个任务可以分配多个候选人,但是只能有一个代理人

    • 方式1:使用task对象的setAssignee方法设置代理人
    • 方式2:使用XML配置
      id
      1
      2
      3
      4
      5
      6
              <humanPerformer>
      <resourceAssignmentExpression>
      <formalExpression>user</formalExpression>
      </resourceAssignmentExpression>
      </humanPerformer>
      > </userTask>
  • 权限分配扩展

    1
    2
    3
    4
    <userTask id="usertask1" name="Task A" activiti:assignee="user1"
    activiti:candidateUsers="angus,angus1" activiti:candidateGroups="boss,management">
    </userTask>
    >

当设置代理人的时候,该任务只属于该代理人

  • 使用任务监听器进行权限分配

    见监听器

  • 使用JUEL分配权限

    1
    2
    3
    4
    <userTask id="usertask1" name="My Task" activiti:candidateUsers="${authService.getCandidateUsers()}"
    activiti:candidateGroups="${authService.getCandidateGroups()}" activiti:assignee="${authService.getAssignee()}"
    ></userTask>
    >

启动流程:

1
2
3
4
Map<String, Object> vars = new HashMap<String, Object>();
vars.put("authService", new AuthService());
ProcessInstance pi = runService.startProcessInstanceById(pd.getId(), vars);
>

AuthService类中方法返回List<String>获取String类型即可

2、服务任务

  • Java Service Task

    • activiti:class:必须是该两个接口的实现类JavaDelegate、ActivityBehavior

      必须写死类路径

    • activiti:delegateExpression

      activiti:delegateExpression="${myDelegate}"

      1
      2
      3
      4
      5
      6
      7
          //MyDelegate实现JavaDelegate和Serializable
      MyDelegate de = new MyDelegate();
      Map<String ,Object> vars = new HashMap<String, Object>();
      vars.put("myDelegate", de);
      // 启动流程
      ProcessInstance pi = runService.startProcessInstanceById(pd.getId(), vars);
      >
    • activiti:expression

      activiti:expression="${myBean.print(execution)}"
      activiti:expression="${execution.setVariable('myName', myBean.name)}"

      1
      2
      3
      4
      5
      6
      Map<String ,Object> vars = new HashMap<String, Object>();
      //print方法传入Execution exe,可以获取当前的任务
      vars.put("myBean", new MyBean());//实现Serializable接口,并且有name成员变量,getName方法
      // 启动流程
      ProcessInstance pi = runService.startProcessInstanceById(pd.getId(), vars);
      >

JavaDelegate 会自动执行,ActivityBehavior 会等待

  • Shell Task
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <serviceTask id="servicetask1" name="Service Task" activiti:type="shell">
    <extensionElements>
    <activiti:field name="command" stringValue="cmd"/>
    <activiti:field name="arg1" stringValue="/c"/>
    <activiti:field name="arg2" stringValue="echo"/>
    <activiti:field name="arg3" stringValue="%JAVA_HOME%"/>
    <activiti:field name="outputVariable" stringValue="javaHome"/>
    </extensionElements>
    </serviceTask>
    >

获取参数值runService.getVariable(pi.getId(), "javaHome")

  • Receive Task
1
2
3
4
5
6
7
8
9
10
// 启动流程
ProcessInstance pi = runService.startProcessInstanceById(pd.getId());
// 查当前的子执行流(只有一个)
Execution exe = runService.createExecutionQuery()
.processInstanceId(pi.getId()).onlyChildExecutions()
.singleResult();
System.out.println(pi.getId() + ", 当前节点:" + exe.getActivityId());
// 让它往前走
runService.trigger(exe.getId());
>
  • Web Service Task

    用不上

    3、其他任务与流程监听器

    其他任务

  • 手工任务

    自己会执行,会记录历史数据

  • 接收任务: RuntimeService.trigger(exe.getId())
  • 邮件任务

    自动发送邮件

  • Mule任务
  • 业务规则任务

任务监听器

同Service Task有三种配置方式:

  • class
  • delegateExpression
  • expression

监听器触发:

  • create

    流程创建时

  • assignment

    流程任务分配

  • complete

    任务完成

1
2
3
4
5
6
7
8
9
10
<userTask id="usertask1" name="User Task" activiti:assignee="crazyit">
<extensionElements>
<activiti:taskListener event="create"
class="org.crazyit.act.c10.MyTaskListener">
<activiti:field name="userName" stringValue="crazyit" /></activiti:taskListener>
<activiti:taskListener event="assignment"
class="org.crazyit.act.c10.TaskListenerAssignment"></activiti:taskListener>
<activiti:taskListener event="complete" class="org.crazyit.act.c10.TaskListenerComplete"></activiti:taskListener>
</extensionElements>
</userTask>

监听器也可以获取流程中设置的参数
监听器实现TaskListener接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyTaskListener implements TaskListener {

private FixedValue userName;

public void setUserName(FixedValue userName) {
this.userName = userName;
}

@Override
public void notify(DelegateTask arg0) {
System.out.println("这是自定义任务监听器, " + userName.getExpressionText());
}

}

流程监听器
监听器触发:

  • start

    流程开始

  • take

    流程经过

  • end

    流程完成

1
2
3
4
5
6
7
8
9
10
11
<extensionElements>
<activiti:executionListener event="start"
class="org.crazyit.act.c10.ExecutionListener">
<activiti:field name="userName" stringValue="crazyit" />
</activiti:executionListener>
<activiti:executionListener event="take"
class="org.crazyit.act.c10.ExecutionListenerAssignment"></activiti:executionListener>
<activiti:executionListener event="end"
class="org.crazyit.act.c10.ExecutionListenerComplete">
</activiti:executionListener>
</extensionElements>

监听器实现类是ExecutionListener

流程网关其他

1、子流程

  • 嵌入式子流程

    子流程与外部任务交互必须经过边界事件

  • 调用式子流程
    调用外部流程

    添加callActivity节点,指定外部流程ID:SubProcess<callActivity id="callactivity1" name="调用其他的流程" calledElement="SubProcess"></callActivity>
    获取外部流程的实例:ProcessInstance piSub = runService.createProcessInstanceQuery(). superProcessInstanceId(pi.getId()).singleResult();
    传递参数:

    1
    2
    3
    4
    5
    <extensionElements>
    <activiti:in source="days" target="newDays"/>
    <activiti:out source="myDays" target="resultDays"/>
    </extensionElements>
    >
  • 事件子流程

    可以由错误、信号、消息、定时器事件触发

  • 事务子流程

    在事务子流程中出现异常,子流程边界错误事件会捕捉到。事务子流程中出现取消结束流程,会触发之前的流程任务的边界补偿事务,同时触发子流程取消边界事务

  • 特别子流程

    6.0 新增,在该子流程中,不存在执行顺序,由执行时决定

2、顺序流与网关

条件顺序流

1
2
3
4
<sequenceFlow id="flow3" sourceRef="exclusivegateway1" targetRef="usertask2">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${days <= 3 || day == 5}]]></conditionExpression>
</sequenceFlow>

如果是条件网关的话,不满足条件会报错。多条满足,会默认走第一个
普通顺序流

一个任务不能出现多条普通顺序流吧

网关

  • 单向网关
    与条件顺序流一起使用,只能有一个条件通过
  • 并行网关

  • 兼容网关
    单向网关和并行网关结合体

  • 事件网关
    和中间事务结合使用,多个任务的时候,哪个任务先触发就执行哪条任务
  • 组合网关
    不支持

3、流程活动的特性

  • 多实例流程活动

    创建多个任务实例

    1
    2
    3
    4
    5
    6
    7
    <serviceTask id="servicetask1" name="Service Task" activiti:class="org.crazyit.act.c10.ForeachDelegate">
    <multiInstanceLoopCharacteristics
    isSequential="false">
    <loopCardinality>3</loopCardinality>
    </multiInstanceLoopCharacteristics>
    </serviceTask>
    >
  • 设置循环数据(6.0版本)

    1
    2
    3
    4
     Map<String, Object> vars = new HashMap<String, Object>();
    vars.put("datas1", datas1); //List<String>格式
    ProcessInstance pi = runService.startProcessInstanceById(pd.getId(), vars);
    >
1
2
3
4
5
6
 <serviceTask id="servicetask1" name="Service Task" activiti:class="org.crazyit.act.c10.ForeachDelegate">
<multiInstanceLoopCharacteristics isSequential="false" activiti:elementVariable="data">
<loopDataInputRef>datas1</loopDataInputRef>
</multiInstanceLoopCharacteristics>
</serviceTask>
>
1
2
3
4
5
6
7
8
//处理类,List集合有多少个元素就执行几次
public class ForeachDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) {
System.out.println("执行服务任务: " + execution.getVariable("data"));
}
}
>

设置了循环了数据,会有内置参数,例如nrOfCompletedInstances是当前执行的实例数
添加<completionCondition>${nrOfCompletedInstances >= 2}</completionCondition>设置条件执行流程

Activiti与BPMN2.0规范

五、流程启动与服务调用API

1、查询

查询所有
通过service获取,各个service查询类似。
service.createGroupQuery().groupName("Group_1").groupType("TYPE_1").list();
分页查询
service.createGroupQuery().listPage(1, 5)
查询单个
service.createGroupQuery().groupName("Group_0").singleResult();
排序
service.createGroupQuery().orderByGroupId().desc().orderByGroupName().asc().list()
自定义查询
service.createNativeGroupQuery(). sql("SELECT * FROM ACT_ID_GROUP where NAME_ = #{name}"). parameter("name", "Group_2").list();
保存
service.newGroup(id); //新增一个执行ID值

###2、流程部署
ZIP

1
2
3
4
FileInputStream fis = new FileInputStream(new File("resource/datas.zip"));
ZipInputStream zis = new ZipInputStream(fis);
builder.addZipInputStream(zis);
builder.deploy();

代码生成流程模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public static void main(String[] args) {
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 存储服务
RepositoryService rs = engine.getRepositoryService();
RuntimeService run = engine.getRuntimeService();

DeploymentBuilder builder = rs.createDeployment();
builder.addBpmnModel("My Process", createProcessModel());

Deployment dep = builder.deploy();

}

private static BpmnModel createProcessModel() {
// 创建BPMN模型对象
BpmnModel model = new BpmnModel();
// 创建一个流程定义
org.activiti.bpmn.model.Process process = new org.activiti.bpmn.model.Process();
model.addProcess(process);
process.setId("myProcess");
process.setName("My Process");
// 开始事件
StartEvent startEvent = new StartEvent();
startEvent.setId("startEvent");
process.addFlowElement(startEvent);
// 用户任务
UserTask userTask = new UserTask();
userTask.setName("User Task");
userTask.setId("userTask");
process.addFlowElement(userTask);
// 结束事件
EndEvent endEvent = new EndEvent();
endEvent.setId("endEvent");
process.addFlowElement(endEvent);
// 添加流程顺序
process.addFlowElement(new SequenceFlow("startEvent", "userTask"));
process.addFlowElement(new SequenceFlow("userTask", "endEvent"));
return model;
}

关闭流程部署验证

1
2
3
4
DeploymentBuilder builder = rs.createDeployment();
builder.addClasspathResource("error/schema_error.bpmn");
builder.disableSchemaValidation(); //关闭
builder.deploy();

查询文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 存储服务
RepositoryService rs = engine.getRepositoryService();

DeploymentBuilder builder = rs.createDeployment();
builder.addClasspathResource("my_text.txt");
Deployment dep = builder.deploy();
// 数据查询
InputStream is = rs.getResourceAsStream(dep.getId(), "my_text.txt");
int count = is.available();
byte[] contents = new byte[count];
is.read(contents);
String result = new String(contents);
//输入结果
System.out.println(result);

查询流程文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 创建流程引擎
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 得到流程存储服务对象
RepositoryService repositoryService = engine.getRepositoryService();
// 部署一份流程文件
Deployment dep = repositoryService.createDeployment()
.addClasspathResource("gen.bpmn").deploy();
// 查询流程定义
//查询流程定义实体
ProcessDefinition def = repositoryService.createProcessDefinitionQuery()
.deploymentId(dep.getId()).singleResult();
// 查询资源文件
InputStream is = repositoryService.getProcessModel(def.getId());
// 读取输入流
int count = is.available();
byte[] contents = new byte[count];
is.read(contents);
String result = new String(contents);
//输入输出结果
System.out.println(result);

查询流程图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 创建流程引擎
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 得到流程存储服务对象
RepositoryService repositoryService = engine.getRepositoryService();
// 部署一份流程文件与相应的流程图文件
Deployment dep = repositoryService.createDeployment()
.addClasspathResource("gen.bpmn").deploy();
// 查询流程定义
ProcessDefinition def = repositoryService.createProcessDefinitionQuery()
.deploymentId(dep.getId()).singleResult();
// 查询资源文件
InputStream is = repositoryService.getProcessDiagram(def.getId());
// 将输入流转换为图片对象
BufferedImage image = ImageIO.read(is);
// 保存为图片文件
File file = new File("resource/result.png");
if (!file.exists()) file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
ImageIO.write(image, "png", fos);
fos.close();
is.close();

删除流程部署

1
2
repositoryService.deleteDeployment(dep.getId());
repositoryService.deleteDeployment(dep.getId(), true); //级联删除(会删除运行实例和历史数据)

3、流程定义

自己指定流程图片

1
2
3
4
5
6
7
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 存储服务
RepositoryService rs = engine.getRepositoryService();

DeploymentBuilder builder = rs.createDeployment();
builder.addClasspathResource("test2.bpmn").addClasspathResource("test2.png");
builder.deploy();

流程中止
流程被中止后是不能被重新启动的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 存储服务
RepositoryService rs = engine.getRepositoryService();

DeploymentBuilder builder = rs.createDeployment();
builder.addClasspathResource("test3.bpmn");
Deployment dep = builder.deploy();

ProcessDefinition def = rs.createProcessDefinitionQuery()
.deploymentId(dep.getId()).singleResult();

System.out.println("id: " + def.getId());
rs.suspendProcessDefinitionByKey(def.getKey());
// 将会抛出异常,因为流程定义被中止了
RuntimeService runService = engine.getRuntimeService();
runService.startProcessInstanceByKey(def.getKey());

启动流程任务权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 存储服务
RepositoryService rs = engine.getRepositoryService();
IdentityService is = engine.getIdentityService();
TaskService ts = engine.getTaskService();
User user = is.newUser(UUID.randomUUID().toString());
user.setFirstName("Angus");
is.saveUser(user);
DeploymentBuilder builder = rs.createDeployment();
builder.addClasspathResource("test3.bpmn");
Deployment dep = builder.deploy();
ProcessDefinition def = rs.createProcessDefinitionQuery()
.deploymentId(dep.getId()).singleResult();
rs.addCandidateStarterUser(def.getId(), user.getId());
//查询该用户有多少个流程可以启动
List<ProcessDefinition> defs = rs.createProcessDefinitionQuery().startableByUser(user.getId()).list();
for(ProcessDefinition de : defs) {
System.out.println(de.getId());
}

###4、流程任务
任务候选人(组)
多少个用户或组能看见这个任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService ts = engine.getTaskService();
IdentityService is = engine.getIdentityService();
// 创建任务
String taskId = UUID.randomUUID().toString();
Task task = ts.newTask(taskId);
task.setName("test");
ts.saveTask(task);
// 创建用户
String userId = UUID.randomUUID().toString();
User user = is.newUser(userId);
user.setFirstName("angus");
is.saveUser(user);
// 设置任务的候选用户组
ts.addCandidateUser(taskId, userId);

/*添加用户到组*/
//is.createMembership(userId, groupId);

List<Task> tasks = ts.createTaskQuery().taskCandidateUser(userId).list();
System.out.println(userId + " 这个用户有权限处理的任务有:");
for(Task t : tasks) {
System.out.println(t.getName());
}

任务持有人
当前处理该任务用户,一个任务只有一个持有人

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService ts = engine.getTaskService();
IdentityService is = engine.getIdentityService();
// 创建任务
String taskId = UUID.randomUUID().toString();
Task task = ts.newTask(taskId);
task.setName("test1");
ts.saveTask(task);
// 创建用户
String userId = UUID.randomUUID().toString();
User user = is.newUser(userId);
user.setFirstName("angus1");
is.saveUser(user);
// 设置任务持有人
ts.setOwner(taskId, userId);
// ts.setOwner(taskId, "e110a0a5-1314-4c0c-9ba9-142447b11dea");
// 根据用户来查询他所持有的任务
List<Task> tasks = ts.createTaskQuery().taskOwner(userId).list();
for(Task t : tasks) {
System.out.println(t.getName());
}
engine.close();

任务代理人

1
2
3
4
5
//任务被认领之后,其他人认领就会报错
ts.claim(taskId, user.getId());

//任务指定代理人
ts.setAssignee(taskId, user.getId());

任务完成
taskService.complete(task.getId());

4、参数与附件

设置参数

  • a、流程配置文件设置

    1
    2
    3
    4
    5
    6
    7
    <!-- process标签里面 -->
    <dataObject id="personName" name="personName"
    itemSubjectRef="xsd:string">
    <extensionElements>
    <activiti:value>Crazyit</activiti:value>
    </extensionElements>
    </dataObject>
  • b、启动流程设置

    1
    2
    3
    4
    5
    6
    7
    Map<String,Object> map = new HashMap<>();
    Person p = new Person();
    p.setId(1);
    p.setName("angus");
    map.put("p", p);
    map.put("key", "val1");
    ProcessInstance pi = runService.startProcessInstanceById(pd.getId(),map);
  • c、服务设置

    1
    2
    runService.setVariable(execution.getId(), "key",value);
    taskService.setVariable(task.getId(), "key", value);
  • d、设置本地参数
    setVariable变成setVariableLocal

获取参数值

1
2
runService.getVariable(execution.getId(), "key");
taskService.getVariable(task.getId(), "key");

附件

5、启动流程

1
2
3
4
5
6
7
//通过ID启动并设置business_key参数
runService.startProcessInstanceById(pd.getId(), "test");
//通过key值启动
runService.startProcessInstanceByKey(pd.getKey());
//通过消息启动,消息开始事件
runService.startProcessInstanceByMessage(message);
//

6、流程操作与数据查询

task流程
taskService.complete(task.getId());
Receive Task流程
该task不会产生task数据,只有execution

1
2
3
4
5
6
7
8
9
// 启动流程
ProcessInstance pi = runService.startProcessInstanceById(pd.getId());
// 查当前的子执行流(只有一个)
Execution exe = runService.createExecutionQuery()
.processInstanceId(pi.getId()).onlyChildExecutions()
.singleResult();
System.out.println(pi.getId() + ", 当前节点:" + exe.getActivityId());
// 让它往前走
runService.trigger(exe.getId());

7、JOB

手动执行任务(act_run_job)

1
2
3
4
Job job = managementService.createJobQuery().singleResult();
//设置重试次数
managementService.setJobRetries(job.getId(), 1);
managementService.executeJob(job.getId());

六、其他

6.0版本支持activiti:candidateGroups=”${prd_add}”
5.X版本只能activiti:candidateGroups=”#{prd_add}”

lightquant wechat
欢迎您订阅灯塔量化公众号!