1.プロセスインスタンス
1.1 プロセスインスタンスとは
プロセス インスタンス (ProcessInstance) は、プロセス定義の実行インスタンスを表します。プロセス インスタンスには、実行中のすべてのノードが含まれます。このオブジェクトを使用して、現在のプロセス インスタンスの進行状況やその他の情報を把握できます。たとえば、ユーザーのコンテンツやプログラム インストール プロセス定義は
プロセスを開始します。これはプロセス インスタンスです。
1.2 ビジネス管理
プロセス定義が Activiti にデプロイされた後、システム内の Activiti を介してプロセスの実行を管理できますが、プロセス インスタンスをビジネス データに関連付ける場合は、Activiti で予約されている BusinessKey (ビジネス ID) を使用する必要があります。関連付ける
実装コード:
/**
* 启动流程实例,添加businessKey
*/
@Test
public void test01(){
// 1.获取ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.获取RuntimeService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
// 3.启动流程实例
ProcessInstance instance = runtimeService
.startProcessInstanceByKey("evection", "1001");
// 4.输出processInstance相关属性
System.out.println("businessKey = "+instance.getBusinessKey());
}
1.3 プロセスインスタンスの停止と起動
実際のシナリオでは、プロセスの変更により、現在実行中のプロセスを削除するのではなく、中断する必要がある場合があります. プロセスが中断されると、実行を続行できなくなります.
1.3.1 すべてのプロセスがハングする
運用プロセスの定義が中断状態になり、プロセス定義配下のすべてのプロセスインスタンスが中断されます。
プロセス定義は一時停止状態にあります。このプロセス定義では、新しいプロセス インスタンスを開始できません。同時に、このプロセス定義の下にあるすべてのプロセス インスタンスが一時停止され、一時停止されます。
/**
* 全部流程挂起实例与激活
*/
@Test
public void test02(){
// 1.获取ProcessEngine对象
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 2.获取RepositoryService对象
RepositoryService repositoryService = engine.getRepositoryService();
// 3.查询流程定义的对象
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("evection")
.singleResult();
// 4.获取当前流程定义的状态
boolean suspended = processDefinition.isSuspended();
String id = processDefinition.getId();
// 5.如果挂起就激活,如果激活就挂起
if(suspended){
// 表示当前定义的流程状态是 挂起的
repositoryService.activateProcessDefinitionById(
id // 流程定义的id
,true // 是否激活
,null // 激活时间
);
System.out.println("流程定义:" + id + ",已激活");
}else{
// 非挂起状态,激活状态 那么需要挂起流程定义
repositoryService.suspendProcessDefinitionById(
id // 流程id
,true // 是否挂起
,null // 挂起时间
);
System.out.println("流程定义:" + id + ",已挂起");
}
}
プロセス定義を一時停止した後、のインスタンス オブジェクトのステータスは 2 に変更されます。
次に、操作のプロセス インスタンスに移動し、例外メッセージをスローします。
次に、中断されたプロセスをアクティブ状態にすると、状態値が 2 から 1 に更新されます。
その後、ビジネスプロセスは正常に処理できます
1.3.2 単一インスタンスのハング
プロセス インスタンス オブジェクトを操作し、単一のプロセスに対して中断操作を実行します。プロセス インスタンスが中断された場合、プロセスは実行を継続せず、現在のプロセスによって定義された他のプロセス インスタンスは妨げられません。プロセス インスタンスの現在のタスクを完了すると、例外がスローされます
/**
* 单个流程实例挂起与激活
*/
@Test
public void test03(){
// 1.获取ProcessEngine对象
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 2.获取RuntimeService
RuntimeService runtimeService = engine.getRuntimeService();
// 3.获取流程实例对象
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId("25001")
.singleResult();
// 4.获取相关的状态操作
boolean suspended = processInstance.isSuspended();
String id = processInstance.getId();
if(suspended){
// 挂起--》激活
runtimeService.activateProcessInstanceById(id);
System.out.println("流程定义:" + id + ",已激活");
}else{
// 激活--》挂起
runtimeService.suspendProcessInstanceById(id);
System.out.println("流程定义:" + id + ",已挂起");
}
}
次に、データベースでステータスの更新を表示できます
2.個人的なタスク
2.1 タスクの所有者を割り当てる
ビジネス プロセスをモデル化するときに、固定タスクの所有者を指定します。
[プロパティ] ビューで、担当者の項目をタスク リーダーとして入力します。
2.1.2 式の代入
UEL 式は Activiti でサポートされています. UEL 式は Java EE6 仕様の一部です. UEL (Unified Expression Language) は統一された式の音声です. Activiti は 2 つの UEL 式をサポートしています: UEL-value と UEL-method
UEL値
担当者でプロセス変数処理を使用する
その後、操作できます
まず、定義されたプロセスを Activiti データベースにデプロイする必要があります
/**
* 先将新定义的流程部署到Activiti中数据库中
*/
@Test
public void test01(){
// 1.获取ProcessEngine对象
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 2.获取RepositoryService进行部署操作
RepositoryService service = engine.getRepositoryService();
// 3.使用RepositoryService进行部署操作
Deployment deploy = service.createDeployment()
.addClasspathResource("bpmn/evection-uel.bpmn") // 添加bpmn资源
.addClasspathResource("bpmn/evection-uel.png") // 添加png资源
.name("出差申请流程-UEL")
.deploy();// 部署流程
// 4.输出流程部署的信息
System.out.println("流程部署的id:" + deploy.getId());
System.out.println("流程部署的名称:" + deploy.getName());
}
デプロイが成功したら、新しいプロセス インスタンスを開始し、作成されたプロセス インスタンスに UEL 式を実際に関連付ける必要があります。
/**
* 创建一个流程实例
* 给流程定义中的 UEL表达式赋值
*/
@Test
public void test02(){
// 获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取RuntimeService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
// 设置 assignee 的取值,
Map<String,Object> map = new HashMap<>();
map.put("assignee0","张三");
map.put("assignee1","李四");
map.put("assignee2","王五");
map.put("assignee3","赵财务");
// 创建流程实例
runtimeService.startProcessInstanceByKey("evection-uel",map);
}
起動が成功すると、act_ru_variable の UEL 式に対応する割り当て情報が表示されます。
UEL法
userBean は、Spring コンテナー内の Bean です。つまり、Bean の getUserId() メソッドを呼び出します。
UEL法とUEL値の組み合わせ
別の例:
${ldapService.findManagerForEmployee(emp)}
ldapService は Spring コンテナーの Bean、findManagerForEmployee は Bean のメソッド、emp は activiti
プロセス変数、emp はパラメーターとして ldapService.findManagerForEmployee メソッドに渡されます。
他の
式は、基本型、Bean、リスト、配列、およびマップの解析をサポートし、条件判断としても使用できます。
次のように:
${order.price > 100 && order.price < 250}
2.1.3 リスナーの割り当て
リスナーは、多くの Activiti プロセス ビジネスを完了するために使用できます。ここではリスナーを使用して担当者の指定を完了させるため、プロセスの設計時に担当者を指定する必要はありません。
イベントオプション
create: タスクが作成された後にトリガーされる
Assignment: タスクが割り当てられた後にトリガーされる
Delete: タスクが完了した後にトリガーされる
All: すべてのイベントによってトリガーされる
カスタムリスナー
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
public class MyTaskListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
if("创建请假单".equals(delegateTask.getName())
&& "create".equals(delegateTask.getEventName())){
// 指定任务的负责人
delegateTask.setAssignee("张三-Listener");
}
}
}
テストコード
/**
* 先将新定义的流程部署到Activiti中数据库中
*/
@Test
public void test01(){
// 1.获取ProcessEngine对象
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 2.获取RepositoryService进行部署操作
RepositoryService service = engine.getRepositoryService();
// 3.使用RepositoryService进行部署操作
Deployment deploy = service.createDeployment()
.addClasspathResource("bpmn/evection-listener.bpmn") // 添加bpmn资源
.addClasspathResource("bpmn/evection-listener.png") // 添加png资源
.name("出差申请流程-UEL")
.deploy();// 部署流程
// 4.输出流程部署的信息
System.out.println("流程部署的id:" + deploy.getId());
System.out.println("流程部署的名称:" + deploy.getName());
}
/**
* 创建一个流程实例
* 给流程定义中的 UEL表达式赋值
*/
@Test
public void test02(){
// 获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取RuntimeService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
// 创建流程实例
runtimeService.startProcessInstanceByKey("evection-listener");
}
2.2 クエリタスク
タスク所有者の To Do タスクを照会する
コードは以下のように表示されます:
// 查询当前个人待执行的任务
@Test
public void findPersonalTaskList() {
// 流程定义key
String processDefinitionKey = "myEvection1";
// 任务负责人
String assignee = "张三";
// 获取TaskService
TaskService taskService = processEngine.getTaskService();
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey(processDefinitionKey)
.includeProcessVariables()
.taskAssignee(assignee)
.list();
for (Task task : taskList) {
System.out.println("----------------------------");
System.out.println("流程实例id: " + task.getProcessInstanceId());
System.out.println("任务id: " + task.getId());
System.out.println("任务负责人: " + task.getAssignee());
System.out.println("任务名称: " + task.getName());
}
}
アソシエイト ビジネス キー
要件:
Activiti の実際のアプリケーションでは、to-do タスクをクエリすると、ビジネス システムの関連情報が表示される場合があります。
例:承認する出張タスクのリストを照会するには、出張オーダーの日付と出張日数などの情報を表示する必要があります。
出張回数などの情報は業務システムには存在しますが、Activiti データベースには存在しないため、Activiti API から出張回数などの情報を照会することはできません。
実現:
to-doタスクを問い合わせる際、businessKey(業務識別子)で業務システムの出張フォームを問い合わせ、出張日数などを問い合わせる。
@Test
public void findProcessInstance(){
// 获取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取TaskService
TaskService taskService = processEngine.getTaskService();
// 获取RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 查询流程定义的对象
Task task = taskService.createTaskQuery()
.processDefinitionKey("myEvection1")
.taskAssignee("张三")
.singleResult();
// 使用task对象获取实例id
String processInstanceId = task.getProcessInstanceId();
// 使用实例id,获取流程实例对象
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
// 使用processInstance,得到 businessKey
String businessKey = processInstance.getBusinessKey();
System.out.println("businessKey=="+businessKey);
}
2.3 タスクの処理
注: 実際のアプリケーションでは、タスクを完了する前に、タスクの担当者がタスクを処理する権限を持っているかどうかを確認する必要があります。
/**
* 完成任务,判断当前用户是否有权限
*/
@Test
public void completTask() {
//任务id
String taskId = "15005";
// 任务负责人
String assingee = "张三";
//获取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 创建TaskService
TaskService taskService = processEngine.getTaskService();
// 完成任务前,需要校验该负责人可以完成当前任务
// 校验方法:
// 根据任务id和任务负责人查询当前任务,如果查到该用户有权限,就完成
Task task = taskService.createTaskQuery()
.taskId(taskId)
.taskAssignee(assingee)
.singleResult();
if(task != null){
taskService.complete(taskId);
System.out.println("完成任务");
}
}
3. プロセス変数
3.1. プロセス変数とは? プロセス
変数はアクティビティにおいて非常に重要な役割を果たします. プロセスの運用にはプロセス変数が必要になることがあります. 業務システムとアクティビティを組み合わせる場合, プロセス変数は不可欠です. プロセス変数はアクティビティがワークフローを管理するための基礎となります. . 管理のニーズによって設定される変数。例えば、出張申請の流れで、出張日数が3日を超える場合は部長が審査、それ以外は担当者が直接審査を行い、出張日数を設定することができます。プロセス変数であり、プロセス フロー中に使用されます。
注: ビジネス データはプロセス変数に格納できますが、Activiti の API を介してプロセス変数をクエリしてビジネス データをクエリできますが、これを使用することはお勧めしません。ビジネス データ クエリはビジネス システムを担当し、Activiti はプロセス変数をプロセス実行のニーズに合わせて作成します。
3.2. プロセス変数のタイプ
pojo がプロセス変数に格納されている場合、シリアライゼーション インターフェイス serializable を実装する必要があります. 新しいフィールドによるデシリアライズを防ぐために、serialVersionUID を生成する必要があります.
3.3. プロセス変数のスコープ
プロセス変数のスコープは、プロセス インスタンス (processInstance)、タスク (タスク)、または実行インスタンス
(execution)にすることができます。
3.3.1. グローバル変数
プロセス変数のデフォルトのスコープはプロセスインスタンスです。プロセス変数のスコープがプロセスインスタンスの場合、グローバル変数と呼ぶことができます
知らせ:
例: グローバル変数: userId (変数名)、zhangsan (変数値)
グローバル変数内の変数名は重複不可で、同じ名前の変数を設定すると、前に設定した変数の値が後から設定した値で上書きされます。
3.3.2. ローカル変数の
タスクと実行インスタンスは、1 つのタスクと 1 つの実行インスタンスの範囲のみであり、スコープはローカル変数と呼ばれるプロセス インスタンスほど大きくありません。Local 変数のスコープは、異なるタスクまたは異なる実行インスタンスで互いに影響しないため、変数名は影響を受けずに同じにすることができます。ローカル変数名は、グローバル変数名と同じにすることもできますが、効果はありません。
3.4. プロセス変数の使用方法
3.4.1. 属性での UEL 式の使用
担当者に UEL 式を設定でき、式の値はタスクの担当者です (例: ${assignee}, assignee is a)プロセス変数名。
ActivitiはUEL式の値、つまりプロセス変数担当者の値を取得し、タスクの担当者として担当者の値を割り当てます
3.4.2. 接続で UEL 式を使用する 接続
で UEL 式を設定して、フローの方向を決定できます。例: ${価格<10000}。price はプロセス変数名であり、uel 式の結果の型は Boolean です。UEL 式が true の場合、プロセス実行の方向を決定する必要があります。
3.5 プロセス変数の使用
3.5.1 要件
従業員が出張申請書を作成し、部門長が審査します. 部門長の申請が承認された後、3日以内に財務部門が直接承認を申請します. 3 日を超える場合は、ゼネラル マネージャーによって承認されます。
3.5.2 プロセス定義
最初に UEL-value で担当者を設定します
次に、支線に条件を設定します
次に、event.num などのオブジェクト パラメータを介して名前を付けることもできます。
他の行は設定に対応します
次に、関連するリソース ファイルをプロジェクトにコピーできます。
次に、グローバル変数を使用してプロセスを制御します
最初に POJO オブジェクトを作成します
/**
* 出差申请的POJO对象
*/
@Data
public class Evection {
private long id;
private String evectionName;
/**
* 出差的天数
*/
private double num;
private Date beginDate;
private Date endDate;
private String destination;
private String reson;
}
3.5.3.2 プロセスの展開
/**
* 部署流程
*/
@Test
public void test01(){
// 1.获取ProcessEngine对象
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 2.获取RepositoryService进行部署操作
RepositoryService service = engine.getRepositoryService();
// 3.使用RepositoryService进行部署操作
Deployment deploy = service.createDeployment()
.addClasspathResource("bpmn/evection-variable.bpmn") // 添加bpmn资源
.addClasspathResource("bpmn/evection-variable.png") // 添加png资源
.name("出差申请流程-流程变量")
.deploy();// 部署流程
// 4.输出流程部署的信息
System.out.println("流程部署的id:" + deploy.getId());
System.out.println("流程部署的名称:" + deploy.getName());
}
3.5.3.3 プロセス変数の設定
プロセスの開始時にプロセス変数を設定します。変数のスコープはプロセス インスタンス全体です。
/**
* 启动流程实例,设置流程变量
*/
@Test
public void test02(){
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = engine.getRuntimeService();
// 流程定义key
String key = "evection-variable";
// 创建变量集合
Map<String,Object> variables = new HashMap<>();
// 创建出差对象 POJO
Evection evection = new Evection();
// 设置出差天数
evection.setNum(4d);
// 定义流程变量到集合中
variables.put("evection",evection);
// 设置assignee的取值
variables.put("assignee0","张三1");
variables.put("assignee1","李四1");
variables.put("assignee2","王五1");
variables.put("assignee3","赵财务1");
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key, variables);
// 输出信息
System.out.println("获取流程实例名称:"+processInstance.getName());
System.out.println("流程定义ID:" + processInstance.getProcessDefinitionId());
}
任務完了
/**
* 完成任务
*/
@Test
public void test03(){
String key = "evection-variable";
String assignee = "李四1";
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
Task task = taskService.createTaskQuery()
.processDefinitionKey(key)
.taskAssignee(assignee)
.singleResult();
if(task != null){
taskService.complete(task.getId());
System.out.println("任务执行完成...");
}
}
startProcessInstanceByKey メソッドで設定されたプロセス変数のスコープはプロセス インスタンスです.プロセス変数は Map に格納されます.同じプロセス インスタンスのマップ内のキーは同じであり、後者は前者を上書きします.
b.
タスクが完了したときにプロセス変数を設定します. プロセス変数は, タスクが完了した後にのみ他のノードで使用できます. その範囲はプロセスインスタンス全体です. 設定されたプロセス変数のキーがプロセス内にある場合.同じ名前がインスタンスに既に存在する場合、後で設定された変数が以前に設定された変数に置き換わります。
ここでは、出張を作成するタスクが完了したときにプロセス変数を設定する必要があります。
/**
* 启动流程实例,设置流程变量
*/
@Test
public void test02(){
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = engine.getRuntimeService();
// 流程定义key
String key = "evection-variable";
// 创建变量集合
Map<String,Object> variables = new HashMap<>();
// 设置assignee的取值
variables.put("assignee0","张三1");
variables.put("assignee1","李四1");
variables.put("assignee2","王五1");
variables.put("assignee3","赵财务1");
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key, variables);
// 输出信息
System.out.println("获取流程实例名称:"+processInstance.getName());
System.out.println("流程定义ID:" + processInstance.getProcessDefinitionId());
}
/**
* 完成任务
*/
@Test
public void test03(){
String key = "evection-variable";
String assignee = "李四1";
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
Task task = taskService.createTaskQuery()
.processDefinitionKey(key)
.taskAssignee(assignee)
.singleResult();
Map<String,Object> variables = new HashMap<>();
// 创建出差对象 POJO
Evection evection = new Evection();
// 设置出差天数
evection.setNum(4d);
// 定义流程变量到集合中
variables.put("evection",evection);
if(task != null){
taskService.complete(task.getId(),variables);
System.out.println("任务执行完成...");
}
}
注:
現在のタスクを通じてプロセス変数を設定するには、現在のタスク ID を指定する必要があり、現在実行中のタスク ID が存在しない場合は例外がスローされます。
タスクを処理するとき、プロセス変数も map<key,value> を介して設定され、一度に複数の変数を設定できます。
プロセス インスタンス ID によってグローバル変数を設定します。プロセス インスタンスは完了してはなりません。
@Test
public void setGlobalVariableByExecutionId(){
// 当前流程实例执行 id,通常设置为当前执行的流程实例
String executionId="2601";
// 获取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 创建出差pojo对象
Evection evection = new Evection();
// 设置天数
evection.setNum(3d);
// 通过流程实例 id设置流程变量
runtimeService.setVariable(executionId, "evection", evection);
// 一次设置多个值
// runtimeService.setVariables(executionId, variables)
}
注:
executionId は、現在未完了のプロセス インスタンスの実行 ID である必要があります。通常、この ID はプロセス インスタンスの ID を設定します。プロセス変数は、runtimeService.getVariable() を介して取得することもできます。
@Test
public void setGlobalVariableByTaskId(){
//当前待办任务id
String taskId="1404";
// 获取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Evection evection = new Evection();
evection.setNum(3);
//通过任务设置流程变量
taskService.setVariable(taskId, "evection", evection);
//一次设置多个值
//taskService.setVariables(taskId, variables)
}
注:
タスク ID は、act_ru_task に存在する現在の ToDo タスク ID である必要があります。タスクが終了した場合、エラーが報告されるか、プロセス変数は taskService.getVariable() を介して取得できます。
3.5.4 ローカル プロセス変数の設定
3.5.4.1.
タスク処理中のローカル プロセス変数の設定. タスク処理中にローカル プロセス変数を設定する場合、現在実行中のプロセス インスタンスは、タスクの終了前にのみ使用できます. タスクの終了後、この変数は、現在のプロセス インスタンスでは使用できません。クエリの履歴タスク クエリを渡すことができます。
/*
*处理任务时设置local流程变量
*/
@Test
public void completTask() {
//任务id
String taskId = "1404";
// 获取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
// 定义流程变量
Map<String, Object> variables = new HashMap<String, Object>();
Evection evection = new Evection ();
evection.setNum(3d);
// 定义流程变量
Map<String, Object> variables = new HashMap<String, Object>();
// 变量名是holiday,变量值是holiday对象
variables.put("evection", evection);
// 设置local变量,作用域为该任务
taskService.setVariablesLocal(taskId, variables);
// 完成任务
taskService.complete(taskId);
}
説明:
タスクをスコープとするローカル変数を設定すると、各タスクは互いに影響を与えずに同じ名前の変数を設定できます。
@Test
public void setLocalVariableByTaskId(){
// 当前待办任务id
String taskId="1404";
// 获取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Evection evection = new Evection ();
evection.setNum(3d);
// 通过任务设置流程变量
taskService.setVariableLocal(taskId, "evection", evection);
// 一次设置多个值
//taskService.setVariablesLocal(taskId, variables)
}
注:
タスク ID は、act_ru_task に存在する現在の ToDo タスク ID である必要があります。
3.5.4.3. ローカル変数のテスト 1
上記の例で、グローバル変数の設定をローカル変数に変更することは可能ですか? なぜ?
ローカル変数は、タスクの終了後、現在のプロセス インスタンスの実行では使用できません。変数が後続のプロセスの実行で必要な場合は、エラーが報告されます。
3.5.4.4、ローカル変数テスト 2
部門長レビュー、部長レビュー、財務レビュー中にローカル変数を設定し、historyService を介して各履歴タスクをクエリするときに、プロセス変数の値もクエリできます。
コードは以下のように表示されます:
// 创建历史任务查询对象
HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();
// 查询结果包括 local变量
historicTaskInstanceQuery.includeTaskLocalVariables();
for (HistoricTaskInstance historicTaskInstance : list) {
System.out.println("==============================");
System.out.println("任务id:" + historicTaskInstance.getId());
System.out.println("任务名称:" + historicTaskInstance.getName());
System.out.println("任务负责人:" + historicTaskInstance.getAssignee());
System.out.println("任务local变量:"+ historicTaskInstance.getTaskLocalVariables());
}
注: 過去のプロセス変数のクエリ、特に pojo 変数のクエリはデシリアライズする必要がありますが、これはお勧めできません。
4. タスクのグループ化
4.1. 要件
プロセス定義では、タスク リーダーはタスク ノードの担当者に固定され、参加者はプロセス定義時に .bpmn ファイルに固定されます.仮のタスク リーダーが変更された場合、プロセスは定義を変更する必要がある システムのスケーラビリティが低い。
この場合、タスクに対して複数の候補を設定し、候補の中から参加者を選択してタスクを完了することができます。
4.2. タスク候補の設定
フローチャートのタスクノードの構成に候補利用者(candidates)を設定し、複数の候補はカンマで区切ります。
bpmn ファイルを表示
<userTask activiti:candidateUsers="lisi,wangwu" activiti:exclusive="true" id="_3" name="マネージャーの承認"/>
部門長のレビュアーは、リシとワンウのような候補者のグループに設定されていることがわかります. activiti:candiateUsers="user 1, user 2, user 3" を使用して候補者のグループを設定できます.
4.3. グループ タスク
4.3.1. グループ タスクの処理プロセス
a. グループ タスクの指定された候補にクエリを実行し
、候補の現在保留中のタスクをクエリします。候補者はタスクをすぐに処理できません。
b. タスクのピックアップ (要求)
このグループのタスクのすべての候補を要求できます。候補者のグループ タスクを個人的なタスクに変えます。元の候補者がタスクの担当者になります。それを拾った後にタスクを処理したくない場合は? 拾った個人のタスクをグループに戻し、個人のタスクをグループのタスクにする必要があります。
c. 個人タスクの
クエリ クエリ方法は個人タスク部分と同じで、担当者に応じてユーザーが担当する個人タスクをクエリします。
d. 個人タスクを処理する
4.3.2. クエリ グループ タスク
の候補に従ってクエリ グループ タスクを処理する
/**
* 查询组任务
*/
@Test
public void test03(){
String key = "evection1";
String candidateUser = "lisi";
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
List<Task> list = taskService.createTaskQuery()
.processDefinitionKey(key)
.taskCandidateUser(candidateUser)
.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());
}
}
4.3.3、グループタスクをピックアップ
志願者がグループ タスクを取り上げた後、そのタスクは彼自身の個人的なタスクになります。
/**
* 候选人 拾取任务
*/
@Test
public void test04(){
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
String taskId = "72505";
// 候选人
String userId = "lisi";
// 拾取任务
Task task = taskService.createTaskQuery()
.taskId(taskId)
.taskCandidateUser(userId) // 根据候选人查询
.singleResult();
if(task != null){
// 可以拾取任务
taskService.claim(taskId,userId);
System.out.println("拾取成功");
}
}
4.3.4. 個人の ToDo タスクのクエリ
クエリ方法は個人タスククエリと同じ
@Test
public void test03(){
String key = "evection1";
String candidateUser = "lisi";
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
List<Task> list = taskService.createTaskQuery()
.processDefinitionKey(key)
//.taskCandidateUser(candidateUser)
//.taskCandidateOrAssigned(candidateUser)
.taskAssignee(candidateUser)
.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());
}
}
4.3.5. 個人的なタスクの処理
個人的なタスクで
/**
* 完成个人任务
*/
@Test
public void test05(){
String taskId = "72505";
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
taskService.complete(taskId);
System.out.println("完成任务:" + taskId);
}
4.3.6. グループタスクを返す
個人がグループ タスクを処理したくない場合は、グループ タスクを返すことができます。その後、ユーザーはタスクの担当者ではなくなります。
/**
* 归还任务
*/
@Test
public void test06(){
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
String taskId = "75002";
String userId= "zhangsan";
Task task = taskService.createTaskQuery()
.taskId(taskId)
.taskAssignee(userId)
.singleResult();
if(task != null){
// 如果设置为null,归还组任务,任务没有负责人
taskService.setAssignee(taskId,null);
}
}
4,3,7 タスク引継ぎ
タスクの所有者は、他の所有者にタスクを引き継ぎます
/**
* 任务交接
*/
@Test
public void test07(){
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
String taskId = "75002";
String userId= "zhangsan";
Task task = taskService.createTaskQuery()
.taskId(taskId)
.taskAssignee(userId)
.singleResult();
if(task != null){
// 设置该任务的新的负责人
taskService.setAssignee(taskId,"赵六");
}
}
4.3.8、データベーステーブル操作
現在のタスク実行テーブルを照会する
SELECT * FROM act_ru_task
現在実行されているタスクを記録するタスク実行テーブル。タスクは現在グループ タスクであるため、すべての担当者は空です。タスクが取得されると、このフィールドは選択されたユーザーの ID になり、タスクの参加者が照会されます。
SELECT * FROM act_ru_identitylink
タスクの参加者。現在の参照タスク ユーザーまたはグループを記録します。現在のタスクが候補を設定する場合、このテーブルに候補レコードが挿入されます。候補が複数ある場合は、複数挿入されます。act_ru_identitylink に対応する履歴テーブル act_hi_identitylink もあります。 act_ru_identitylink に追加されます。レコードを挿入すると、履歴テーブルにもレコードが挿入されます。ミッション完了
5. ゲートウェイ
ゲートウェイは、プロセスの流れを制御するために使用されます。
5.1 排他的ゲートウェイ ExclusiveGateway
5.1.1 排他的ゲートウェイとは:
排他的ゲートウェイは、プロセスの決定を実装するために使用されます。このゲートウェイに対して処理が実行されると、すべての分岐で条件が真かどうかが判定され、真であれば分岐が実行されます。
注: 排他的ゲートウェイは、実行のために真のブランチのみを選択します。両方の分岐条件が true の場合、排他的ゲートウェイは、ID 値が小さい方の分岐を選択して実行します。
専用ゲートウェイを使用する理由
分岐は、接続の条件条件に分岐条件を設定するなど、専用ゲートウェイなしで実装することもできます。コネクションに条件条件を設定するデメリット:条件を満たさない場合、処理が終了(異常終了)します。専用ゲートウェイを使用してブランチの方向を決定する場合は、次のようになります。
ゲートウェイから出る回線のすべての条件が満たされない場合、システムは例外をスローします。
org.activiti.engine.ActivitiException: No outgoing sequence flow of the exclusive gateway 'exclusivegateway1' could be selected for continuing the process
at org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior.leave(ExclusiveGatewayActivityBehavior.java:85)
5.1.2 プロセス定義
赤いボックス内の専用ゲートウェイ アイコン:
部門長による審査後、専用ゲートウェイへ行く 専用ゲートウェイからは、出張回数が3日以上かどうかの判定と、出張回数が3日以上かどうかの判定の2つの分岐があります。旅行は 3 日以下です。分岐条件を設定するときに、すべての分岐条件が真でない場合、エラーが報告されます。
org.activiti.engine.ActivitiException: No outgoing sequence flow of the exclusive gateway 'exclusivegateway1' could be selected for continuing the process
at org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior.leave(ExclusiveGatewayActivityBehavior.java:85)
5.2 パラレルゲートウェイ ParallelGateway
並列ゲートウェイを使用すると、プロセスを複数のブランチに分割でき、複数のブランチをまとめることもできます. 並列ゲートウェイの機能は、着信および発信の順次フローに基づいています:
フォークブランチ:
すべての出力シーケンス フローが並列に実行され、各シーケンス フローの同時分岐が作成されます。
l 集約に参加:
並列ゲートウェイに到着し、シーケンシャル フローのすべての受信ブランチが到着するまでそこで待機するすべての受信ブランチは、フローが収束ゲートウェイを通過します。
同じ並列ゲートウェイに複数の着信シーケンス フローと複数の発信シーケンス フローがある場合、分岐機能と収束機能の両方があることに注意してください。この時点で、ゲートウェイは最初にすべての着信シーケンス フローを集約し、次にそれらを複数の並列ブランチに分割します。
他のゲートウェイとの主な違いは、並列ゲートウェイが条件を解析しないことです。 シーケンスフローで条件を定義しても無視されます。
例:
説明します:
技術管理者とプロジェクト管理者は 2 つの実行ブランチであり、act_ru_execution テーブルには技術管理者とプロジェクト管理者の 2 つのレコードがあり、act_ru_execution にはプロセス インスタンスを示す別のレコードがあります。テクニカル マネージャーとプロジェクト マネージャーのタスクがすべて完了すると、収束点で収束し、parallelGateway パラレル ゲートウェイを通過します。並列ゲートウェイは、複数の参加者が共同で処理するタスクであるカウンターサイン タスクのビジネス アプリケーションでよく使用されます。
5.2.2赤いボックス内のプロセス定義パラレル ゲートウェイ アイコン:
5.2.3
パラレル ゲートウェイ データベースに対してテストを実行すると、追跡は次のようになります。 現在のタスク テーブル: SELECT * FROM act_ru_task
上: 現在実行中の 2 つのタスクがあります。プロセスインスタンス実行テーブルのクエリ: SELECT * FROM act_ru_execution
上の図では、現在のプロセス インスタンスに複数のブランチ (2 つ) が実行されていることが示されています。
並列タスクの実行:
並列タスクの実行は前後に分かれておらず、タスクの担当者が実行できます。
技術管理者タスクの実行後、現在のタスク テーブルをクエリします SELECT * FROM act_ru_task
現在のタスク テーブル act_ru_task_ 内の完了したテクニカル マネージャー タスクが削除されました。
プロセス インスタンスの実行テーブル: SELECT * FROM act_ru_execution には、複数のブランチと、並列ゲートウェイを備えたシンク ノードがあります。
並列ゲートウェイを備えた収束ノード: ブランチが収束に到着し、他のブランチが到着するのを待っていることを意味します。
すべてのブランチ タスクが完了し、集約ノード:
プロセス インスタンス実行テーブル: SELECT * FROM act_ru_execution に到達すると、実行プロセス インスタンスがゼネラル マネージャーによって承認され、プロセス実行がパラレル ゲートウェイを通過したことが示されます。
概要: すべてのブランチがシンク ノードに到達し、パラレル ゲートウェイの実行が完了します。
5.3 インクルーシブ ゲートウェイ
包括的ゲートウェイは、排他的ゲートウェイと並列ゲートウェイの組み合わせと見なすことができます。排他ゲートウェイと同様に、発信シーケンス フローで条件を定義でき、それを含むゲートウェイがそれらを解決します。ただし、主な違いは、コンテインメント ゲートウェイは、並列ゲートウェイと同様に、複数のシーケンス フローを選択できることです。
ゲートウェイを含む機能は、着信および発信シーケンス フローに基づいています。
l ブランチ:
すべての出力シーケンス フロー条件が解決され、true と評価されたシーケンス フローは並行して実行を継続し、シーケンス フローごとに分岐を作成します。
l 収束:
含まれるゲートウェイに到着するすべての並列ブランチは、シーケンス フローに入るプロセス トークンを含む各ブランチが到着するまで待機状態になります。これがパラレルゲートウェイとの最大の違いです。つまり、包含ゲートウェイは、実行のために選択された着信シーケンス フローのみを待機します。収束後、フローは包含ゲートウェイを通過して続行します。
5.3.2 プロセス定義:
出張申請は、3 日以上の場合はプロジェクト マネージャの承認が必要であり、3 日未満の場合は技術マネージャの承認が必要です。人事マネージャーによって承認されます。
赤いボックス内にゲートウェイ アイコンが含まれています。
プロセスを定義します。
注: ゲートウェイを含む各ブランチの接続に条件 condition を設定します。
5.3.3
プロセス変数がゲートウェイ設定の条件に存在しないかどうかをテストすると、エラーが報告されます。
org.activiti.engine.ActivitiException: Unknown property used in expression: ${evection.num>=3}
プロセス変数 evecion.num は、プロセスの開始時に設定する必要があります。
1) プロセスが最初のゲートウェイに到達すると、条件に従って、現在どの分岐に進むかを判断します。
プロセスインスタンス実行テーブル: SELECT * FROM act_ru_execution
最初のレコード: ゲートウェイ ブランチが含まれます。
最後の 2 つのレコードは、実行される 2 つの分岐を表します:
ACT_ID = "_13" はプロジェクト マネージャーを表します Shenpin
ACT_ID = "_5" は HR マネージャーの承認を表します
現在のタスク リスト: ACT_RU_TASK
上の図では、プロジェクト マネージャーの承認と人事マネージャーの承認が現在のタスクであり、並行して実行されています。
最初に収束ノードの分岐に移動する分岐実行がある場合、他の実行分岐が収束ノードに移動するまで待機する必要があります。
2) 最初にプロジェクト マネージャーの承認を実行し、次に現在のタスク テーブルをクエリします: ACT_RU_TASK
現在のタスクは、人事マネージャーによる承認が必要です。
プロセスインスタンス実行テーブル: SELECT * FROM act_ru_execution
人事部長の枝はまだ存在していることがわかり、プロジェクト部長の枝は ACT_ID=_18 のノードに到達しています。ACT_ID=__18 は 2 番目の包含ゲートウェイです. このとき、実行する分岐が 2 つあるため、包含ゲートウェイはすべての分岐が収束するのを待ってから実行を完了します。
3) HR マネージャーの承認を実行し
、現在のタスク リストをクエリします: ACT_RU_TASK
現在のタスク リストは、HR マネージャーによって承認されなくなりました。これは、HR マネージャーの承認が完了したことを示します。プロセスインスタンス実行テーブル: SELECT * FROM act_ru_execution
包含ゲートウェイの実行が完了すると、ブランチと集約は act_ru_execution から削除されます。
まとめ: 分岐する際には条件を判断する必要があり、条件に合致した分岐が実行され、条件に合致した分岐が最終的に集約されます。
5.4 イベントゲートウェイ EventGateway
イベント ゲートウェイを使用すると、イベントに基づいてフローを決定できます。ゲートウェイの各発信シーケンス フローは、中間キャプチャ イベントに接続されます。プロセスがイベントベースのゲートウェイに到達すると、ゲートウェイは待機状態になり、実行が中断されます。同時に、発信シーケンス フローごとに相対的なイベント サブスクリプションが作成されます。
イベント ゲートウェイのアウトバウンド シーケンス フローは、通常のシーケンス フローとは異なります。これらのシーケンス フローは、実際には「実行」されません。代わりに、プロセス エンジンは、イベント ゲートウェイに対して実行中のプロセスがサブスクライブする必要があるイベントを決定します。次の条件を考慮する必要があります。
イベント ゲートウェイには、2 つ以上の送信シーケンス フローが必要です。
イベント ゲートウェイの後では、intermediateCatchEvent タイプのみを使用できます (Activiti は、イベント ゲートウェイに基づく receiveTask をサポートしていません)。イベント ゲートウェイに
接続された中間キャプチャ イベントには、1 つのみが必要です。入場順の流れ。
5.4.1 プロセス定義
赤いボックス内のイベント ゲートウェイ アイコン
中間キャッチイベント:
IntermediateCatchEvent でサポートされるイベント タイプ:
メッセージ イベント: メッセージ イベント
シグナル イベント: シグナル イベント
タイマー イベント: タイミング イベント
イベント ゲートウェイを使用してプロセスを定義します。
ここでは上級編の内容を紹介します。