Каталог статей
- 6. Начало работы с Activiti7
- 7. Activiti7 расширенный
6. Начало работы с Activiti7
6.1 Моделирование бизнес-процессов
6.1.1 Построение блок-схемы
resource
Создайте новый каталог в каталоге для bpmn
хранения всех файлов процесса. bpmn
Создайте новый каталог в каталоге leave.bpmn
со следующим содержимым:
6.1.2 Назначьте руководителей задач
- Назначьте ответственного за каждый узел задачи. Например, рецензентом руководителя отдела является Ли Си.
6.1.3 Блок-схема создания формата png
bpmn
Файл по сути имеет формат xml. Когда мы его открываем, мы видим формат изображения, потому что мы установили плагин actiBPM в IDEA.
Если мы bpmn
развернем файл в веб-среде, мы сможем видеть только информацию XML и не сможем видеть графику, подобную приведенной выше.
bpmn
Мы можем сгенерировать файл на основе файла перед развертыванием , а png
затем одновременно развернуть файл в веб-среде. Если мы хотим просмотреть блок-схему, мы можем прочитать файл через Activiti . Затем мы экспортируем его как файлbpmn
png
png
bpmn
png
- Переименуйте
leave.bpmn
файл вleave.xml
файл
- Щелкните правой кнопкой мыши по
leave.xml
файлу -->Diagrams
-->Show BPMN Designer...
-
Нажмите кнопку экспорта и сохраните его в
resource/bpmn
том же каталоге. -
После экспорта
png
переименуйтеleave.xml
его вleave.bpmn
6.2 Определение процесса развертывания
- Развертывание определения процесса с помощью RepositoryService.
package cn.wolfcode.demo;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.junit.Test;
/**
* Created by wolfcode
*/
public class ActivitiTest {
@Test
public void testDeploy(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/leave.bpmn")
.addClasspathResource("bpmn/leave.png")
.name("请假流程")
.deploy();
//输出部署的一些信息
System.out.println("流程部署ID:"+deployment.getId());
System.out.println("流程部署名称:"+deployment.getName());
}
}
Просматривая логи, мы обнаружили, что операции по развертыванию будут следующими.
- Таблица свойств механизма ACT_GE_PROPERTY
Preparing: update ACT_GE_PROPERTY SET REV_ = ?, VALUE_ = ? where NAME_ = ? and REV_ = ?
Parameters: 2(Integer), 2501(String), next.dbid(String), 1(Integer)
- Таблица определения процесса ACT_RE_PROCDEF
Preparing: insert into ACT_RE_PROCDEF(ID_, REV_, CATEGORY_, NAME_, KEY_, VERSION_, DEPLOYMENT_ID_, RESOURCE_NAME_, DGRM_RESOURCE_NAME_, DESCRIPTION_, HAS_START_FORM_KEY_, HAS_GRAPHICAL_NOTATION_ , SUSPENSION_STATE_, TENANT_ID_, ENGINE_VERSION_) values (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Parameters: leaveProcess:1:4(String), http://www.activiti.org/test(String), 请假流程(String), leaveProcess(String), 1(Integer), 1(String), bpmn/leave.bpmn(String), bpmn/leave.png(String), null, false(Boolean), true(Boolean), 1(Integer), (String), null
- Таблица развертывания процесса ACT_RE_DEPLOYMENT
Preparing: insert into ACT_RE_DEPLOYMENT(ID_, NAME_, CATEGORY_, KEY_, TENANT_ID_, DEPLOY_TIME_, ENGINE_VERSION_) values(?, ?, ?, ?, ?, ?, ?)
Parameters: 1(String), 请假流程(String), null, null, (String), 2021-06-02 11:01:44.838(Timestamp), null
- Таблица двоичных ресурсов ACT_GE_BYTEARRAY
Preparing: INSERT INTO ACT_GE_BYTEARRAY(ID_, REV_, NAME_, BYTES_, DEPLOYMENT_ID_, GENERATED_) VALUES (?, 1, ?, ?, ?, ?) , (?, 1, ?, ?, ?, ?)
Parameters: 2(String), bpmn/leave.png(String), java.io.ByteArrayInputStream@7fe7c640(ByteArrayInputStream), 1(String), false(Boolean), 3(String), bpmn/leave.bpmn(String), java.io.ByteArrayInputStream@4c4748bf(ByteArrayInputStream), 1(String), false(Boolean)
6.3 Запуск экземпляра процесса
- После развертывания определения процесса в Activiti бизнес-процессом можно управлять с помощью рабочего процесса.
- Для этого процесса запуск процесса означает инициирование новой формы заявления на отпуск, что эквивалентно взаимосвязи между классами Java и объектами Java. После определения класса вам необходимо создать объект с помощью new. Конечно, вы также можете создать несколько объектов.
- Для процесса подачи заявления на отпуск Чжан Сану необходимо запустить экземпляр процесса, чтобы инициировать форму заявления на отпуск, а Ли Си необходимо запустить экземпляр процесса, чтобы инициировать форму запроса на отпуск.
@Test
public void testStartProcess(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RuntimeService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
//根据流程定义的key启动流程实例,这个key是在定义bpmn的时候设置的
ProcessInstance instance = runtimeService.
startProcessInstanceByKey("leaveProcess");
//获取流程实例的相关信息
System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
System.out.println("流程实例的id = " + instance.getId());
}
Просматривая логи, мы обнаружили, что процесс запуска будет работать, как показано ниже.
- Таблица исторических задач ACT_HI_TASKINST
Preparing: insert into ACT_HI_TASKINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, EXECUTION_ID_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, OWNER_, ASSIGNEE_, START_TIME_, CLAIM_TIME_, END_TIME_, DURATION_, DELETE_REASON_, TASK_DEF_KEY_, FORM_KEY_, PRIORITY_, DUE_DATE_, CATEGORY_, TENANT_ID_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
Parameters: 2505(String), leaveProcess:1:4(String), 2501(String), 2502(String), 部门经理审批(String), null, null, null, 李四(String), 2021-06-02 16:34:52.827(Timestamp), null, null, null, null, _4(String), null, 50(Integer), null, null, (String)
- Таблица экземпляров исторических процессов ACT_HI_PROCINST
Preparing: insert into ACT_HI_PROCINST ( ID_, PROC_INST_ID_, BUSINESS_KEY_, PROC_DEF_ID_, START_TIME_, END_TIME_, DURATION_, START_USER_ID_, START_ACT_ID_, END_ACT_ID_, SUPER_PROCESS_INSTANCE_ID_, DELETE_REASON_, TENANT_ID_, NAME_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
Parameters: 2501(String), 2501(String), null, leaveProcess:1:4(String), 2021-06-02 16:34:52.798(Timestamp), null, null, null, _2(String), null, null, null, (String), null
- ACT_HI_ACTINST Таблица информации об исторических действиях
Preparing: insert into ACT_HI_ACTINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, EXECUTION_ID_, ACT_ID_, TASK_ID_, CALL_PROC_INST_ID_, ACT_NAME_, ACT_TYPE_, ASSIGNEE_, START_TIME_, END_TIME_, DURATION_, DELETE_REASON_, TENANT_ID_ ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) , (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Parameters: 2503(String), leaveProcess:1:4(String), 2501(String), 2502(String), _2(String), null, null, StartEvent(String), startEvent(String), null, 2021-06-02 16:34:52.815(Timestamp), 2021-06-02 16:34:52.816(Timestamp), 1(Long), null, (String), 2504(String), leaveProcess:1:4(String), 2501(String), 2502(String), _4(String), 2505(String), null, 部门经理审批(String), userTask(String), 李四(String), 2021-06-02 16:34:52.817(Timestamp), null, null, null, (String)
- Таблица исторических связей ACT_HI_IDENTITYLINK
Preparing: insert into ACT_HI_IDENTITYLINK (ID_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_) values (?, ?, ?, ?, ?, ?)
Parameters: 2506(String), participant(String), 李四(String), null, null, 2501(String)
- Таблица экземпляров выполнения ACT_RU_EXECUTION во время выполнения
insert into ACT_RU_EXECUTION (ID_, REV_, PROC_INST_ID_, BUSINESS_KEY_, PROC_DEF_ID_, ACT_ID_, IS_ACTIVE_, IS_CONCURRENT_, IS_SCOPE_,IS_EVENT_SCOPE_, IS_MI_ROOT_, PARENT_ID_, SUPER_EXEC_, ROOT_PROC_INST_ID_, SUSPENSION_STATE_, TENANT_ID_, NAME_, START_TIME_, START_USER_ID_, IS_COUNT_ENABLED_, EVT_SUBSCR_COUNT_, TASK_COUNT_, JOB_COUNT_, TIMER_JOB_COUNT_, SUSP_JOB_COUNT_, DEADLETTER_JOB_COUNT_, VAR_COUNT_, ID_LINK_COUNT_) values (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) , (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Parameters: 2501(String), 2501(String), null, leaveProcess:1:4(String), null, true(Boolean), false(Boolean), true(Boolean), false(Boolean), false(Boolean), null, null, 2501(String), 1(Integer), (String), null, 2021-06-02 16:34:52.798(Timestamp), null, false(Boolean), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 2502(String), 2501(String), null, leaveProcess:1:4(String), _4(String), true(Boolean), false(Boolean), false(Boolean), false(Boolean), false(Boolean), 2501(String), null, 2501(String), 1(Integer), (String), null, 2021-06-02 16:34:52.813(Timestamp), null, false(Boolean), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer)
- Таблица задач времени выполнения ACT_RU_TASK
Preparing: insert into ACT_RU_TASK (ID_, REV_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, PRIORITY_, CREATE_TIME_, OWNER_, ASSIGNEE_, DELEGATION_, EXECUTION_ID_, PROC_INST_ID_, PROC_DEF_ID_, TASK_DEF_KEY_, DUE_DATE_, CATEGORY_, SUSPENSION_STATE_, TENANT_ID_, FORM_KEY_, CLAIM_TIME_) values (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
Parameters: 2505(String), 部门经理审批(String), null, null, 50(Integer), 2021-06-02 16:34:52.817(Timestamp), null, 李四(String), null, 2502(String), 2501(String), leaveProcess:1:4(String), _4(String), null, null, 1(Integer), (String), null, null
- Таблица связей идентификаторов среды выполнения ACT_RU_IDENTITYLINK
Preparing: insert into ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_) values (?, 1, ?, ?, ?, ?, ?, ?)
Parameters: 2506(String), participant(String), 李四(String), null, null, 2501(String), null
6.4 Запрос задачи
- После запуска процесса лицо, отвечающее за каждую задачу, может запросить задачи, которые ему необходимо обработать в данный момент, а запрошенные задачи являются задачами пользователя.
@Test
public void testSelectTodoTaskList(){
//任务负责人
String assignee = "李四";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//获取任务集合
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("leaveProcess")
.taskAssignee(assignee)
.list();
//遍历任务列表
for(Task task:taskList){
System.out.println("流程定义id = " + task.getProcessDefinitionId());
System.out.println("流程实例id = " + task.getProcessInstanceId());
System.out.println("任务id = " + task.getId());
System.out.println("任务名称 = " + task.getName());
}
}
Просматривая журналы, мы обнаружили, что задача запроса будет работать, как показано ниже.
- Таблица задач времени выполнения ACT_RU_TASK
- Таблица определения процесса ACT_RE_PROCDEF
Preparing: select distinct RES.* from ACT_RU_TASK RES inner join ACT_RE_PROCDEF D on RES.PROC_DEF_ID_ = D.ID_ WHERE RES.ASSIGNEE_ = ? and D.KEY_ = ? order by RES.ID_ asc LIMIT ? OFFSET ?
Parameters: 李四(String), leaveProcess(String), 2147483647(Integer), 0(Integer)
6.5 Обработка задач
- Руководитель задач запрашивает задачи, выбирает задачи для обработки и выполняет задачи.
@Test
public void testCompleteTask(){
//任务负责人
String assignee = "李四";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//获取任务集合
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("leaveProcess")
.taskAssignee(assignee)
.list();
//遍历任务列表
for(Task task:taskList){
taskService.complete(task.getId());
}
}
Просматривая журналы, мы обнаружили, что задача запроса будет работать, как показано ниже.
- Таблица свойств механизма ACT_GE_PROPERTY
Preparing: update ACT_GE_PROPERTY SET REV_ = ?, VALUE_ = ? where NAME_ = ? and REV_ = ?
Parameters: 4(Integer), 7501(String), next.dbid(String), 3(Integer)
- Таблица исторических задач ACT_HI_TASKINST
Preparing: insert into ACT_HI_TASKINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, EXECUTION_ID_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, OWNER_, ASSIGNEE_, START_TIME_, CLAIM_TIME_, END_TIME_, DURATION_, DELETE_REASON_, TASK_DEF_KEY_, FORM_KEY_, PRIORITY_, DUE_DATE_, CATEGORY_, TENANT_ID_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
Parameters: 5002(String), leaveProcess:1:4(String), 2501(String), 2502(String), 人事复批(String), null, null, null, 王五(String), 2021-06-02 16:39:19.036(Timestamp), null, null, null, null, _5(String), null, 50(Integer), null, null, (String)
- ACT_HI_ACTINST Таблица информации об исторических действиях
Preparing: insert into ACT_HI_ACTINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, EXECUTION_ID_, ACT_ID_, TASK_ID_, CALL_PROC_INST_ID_, ACT_NAME_, ACT_TYPE_, ASSIGNEE_, START_TIME_, END_TIME_, DURATION_, DELETE_REASON_, TENANT_ID_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
Parameters: 5001(String), leaveProcess:1:4(String), 2501(String), 2502(String), _5(String), 5002(String), null, 人事复批(String), userTask(String), 王五(String), 2021-06-02 16:39:19.025(Timestamp), null, null, null, (String)
- Таблица исторических связей ACT_HI_IDENTITYLINK
Preparing: insert into ACT_HI_IDENTITYLINK (ID_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_) values (?, ?, ?, ?, ?, ?)
Parameters: 5003(String), participant(String), 王五(String), null, null, 2501(String)
- Таблица задач времени выполнения ACT_RU_TASK
Preparing: insert into ACT_RU_TASK (ID_, REV_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, PRIORITY_, CREATE_TIME_, OWNER_, ASSIGNEE_, DELEGATION_, EXECUTION_ID_, PROC_INST_ID_, PROC_DEF_ID_, TASK_DEF_KEY_, DUE_DATE_, CATEGORY_, SUSPENSION_STATE_, TENANT_ID_, FORM_KEY_, CLAIM_TIME_) values (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
Parameters: 5002(String), 人事复批(String), null, null, 50(Integer), 2021-06-02 16:39:19.025(Timestamp), null, 王五(String), null, 2502(String), 2501(String), leaveProcess:1:4(String), _5(String), null, null, 1(Integer), (String), null, null
- Таблица связей идентификаторов среды выполнения ACT_RU_IDENTITYLINK
Preparing: insert into ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_) values (?, 1, ?, ?, ?, ?, ?, ?)
Parameters: 5003(String), participant(String), 王五(String), null, null, 2501(String), null
- Таблица экземпляров выполнения ACT_RU_EXECUTION во время выполнения
Preparing: update ACT_RU_EXECUTION set REV_ = ?, BUSINESS_KEY_ = ?, PROC_DEF_ID_ = ?, ACT_ID_ = ?, IS_ACTIVE_ = ?, IS_CONCURRENT_ = ?, IS_SCOPE_ = ?, IS_EVENT_SCOPE_ = ?, IS_MI_ROOT_ = ?, PARENT_ID_ = ?, SUPER_EXEC_ = ?, ROOT_PROC_INST_ID_ = ?, SUSPENSION_STATE_ = ?, NAME_ = ?, IS_COUNT_ENABLED_ = ?, EVT_SUBSCR_COUNT_ = ?, TASK_COUNT_ = ?, JOB_COUNT_ = ?, TIMER_JOB_COUNT_ = ?, SUSP_JOB_COUNT_ = ?, DEADLETTER_JOB_COUNT_ = ?, VAR_COUNT_ = ?, ID_LINK_COUNT_ = ? where ID_ = ? and REV_ = ?
Parameters: 2(Integer), null, leaveProcess:1:4(String), _5(String), true(Boolean), false(Boolean), false(Boolean), false(Boolean), false(Boolean), 2501(String), null, 2501(String), 1(Integer), null, false(Boolean), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 2502(String), 1(Integer)
- Таблица исторических задач ACT_HI_TASKINST
Preparing: update ACT_HI_TASKINST set PROC_DEF_ID_ = ?, EXECUTION_ID_ = ?, NAME_ = ?, PARENT_TASK_ID_ = ?, DESCRIPTION_ = ?, OWNER_ = ?, ASSIGNEE_ = ?, CLAIM_TIME_ = ?, END_TIME_ = ?, DURATION_ = ?, DELETE_REASON_ = ?, TASK_DEF_KEY_ = ?, FORM_KEY_ = ?, PRIORITY_ = ?, DUE_DATE_ = ?, CATEGORY_ = ? where ID_ = ?
Parameters: leaveProcess:1:4(String), 2502(String), 部门经理审批(String), null, null, null, 李四(String), null, 2021-06-02 16:39:18.995(Timestamp), 266168(Long), null, _4(String), null, 50(Integer), null, null, 2505(String)
- Таблица исторических задач ACT_HI_TASKINST
Preparing: update ACT_HI_ACTINST set EXECUTION_ID_ = ?, ASSIGNEE_ = ?, END_TIME_ = ?, DURATION_ = ?, DELETE_REASON_ = ? where ID_ = ?
Parameters: 2502(String), 李四(String), 2021-06-02 16:39:19.009(Timestamp), 266192(Long), null, 2504(String)
- Таблица задач времени выполнения ACT_RU_TASK
Preparing: delete from ACT_RU_TASK where ID_ = ? and REV_ = ?
Parameters: 2505(String), 1(Integer)
6.6 Добавление комментариев для утверждения
- Перед выполнением задачи вы можете добавить к задаче комментарии по согласованию, которые будут храниться в таблице истории, а позже мы сможем просмотреть комментарии в истории согласований.
@Test
public void testAddComment(){
//任务负责人
String assignee = "王五";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//获取任务集合
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("leaveProcess")
.taskAssignee(assignee)
.list();
//遍历任务列表
for(Task task:taskList){
//在任务执行之前任务添加批注信息
taskService.addComment(task.getId(),task.getProcessInstanceId(),task.getName()+"审批通过");
taskService.complete(task.getId());
}
}
Просматривая журнал, мы обнаружили, что остальные операции соответствуют таблицам, обработанным задачей, но добавление комментариев приведет к вставке записей в следующую таблицу:
Preparing: insert into ACT_HI_COMMENT (ID_, TYPE_, TIME_, USER_ID_, TASK_ID_, PROC_INST_ID_, ACTION_, MESSAGE_, FULL_MSG_) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
Parameters: 7501(String), comment(String), 2021-06-02 16:43:09.13(Timestamp), null, 5002(String), 2501(String), AddComment(String), 人事复批审批通过(String), java.io.ByteArrayInputStream@1b765a2c(ByteArrayInputStream)
6.6. Просмотр исторических разрешений
- Пользователи могут просматривать исторические записи утверждений.
@Test
public void testSelectHistoryTask(){
//流程实例ID
String processInstanceId = "2501";
//任务审核人
String taskAssignee = "王五";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取historyService
HistoryService historyService = processEngine.getHistoryService();
//获取taskService
TaskService taskService = processEngine.getTaskService();
//获取历史审核信息
List<HistoricActivityInstance> list = historyService
.createHistoricActivityInstanceQuery()
.activityType("userTask")//只获取用户任务
.processInstanceId(processInstanceId)
.taskAssignee(taskAssignee)
.finished()
.list();
for(HistoricActivityInstance instance:list){
System.out.println("任务名称:"+instance.getActivityName());
System.out.println("任务开始时间:"+instance.getStartTime());
System.out.println("任务结束时间:"+instance.getEndTime());
System.out.println("任务耗时:"+instance.getDurationInMillis());
//获取审核批注信息
List<Comment> taskComments = taskService.getTaskComments(instance.getTaskId());
if(taskComments.size()>0){
System.out.println("审批批注:"+taskComments.get(0).getFullMessage());
}
}
}
7. Activiti7 расширенный
7.1 Связано с определением процесса
7.1.1 Запрос определения процесса
- Запрос информации, связанной с процессом, включая определение процесса, развертывание процесса и версию определения процесса.
@Test
public void testDefinitionQuery(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取仓库服务
RepositoryService repositoryService = processEngine.getRepositoryService();
//获取流程定义集合
List<ProcessDefinition> processDefinitionList = repositoryService
.createProcessDefinitionQuery()
.processDefinitionKey("leaveProcess")
.list();
//遍历集合
for (ProcessDefinition definition:processDefinitionList){
System.out.println("流程定义ID:"+definition.getId());
System.out.println("流程定义名称:"+definition.getName());
System.out.println("流程定义key:"+definition.getKey());
System.out.println("流程定义版本:"+definition.getVersion());
System.out.println("流程部署ID:"+definition.getDeploymentId());
System.out.println("====================");
}
}
7.1.2 Процесс загрузки ресурсов
-
Теперь наши файлы ресурсов процесса загружены в базу данных. Если другие пользователи захотят просмотреть эти файлы ресурсов, они могут загрузить файлы ресурсов локально из базы данных.
@Test public void testDownloadResource() throws Exception { //创建ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取仓库服务 RepositoryService repositoryService = processEngine.getRepositoryService(); //获取流程定义集合 List<ProcessDefinition> list = repositoryService .createProcessDefinitionQuery() .processDefinitionKey("leaveProcess") .orderByProcessDefinitionVersion()//按照版本排序 .desc()//降序 .list(); //获取最新那个 ProcessDefinition definition =list.get(0); //获取部署ID String deploymentId = definition.getDeploymentId(); //获取bpmn的输入流 InputStream bpmnInput = repositoryService.getResourceAsStream( deploymentId, definition.getResourceName()); //获取png的输入流 InputStream pngInput = repositoryService.getResourceAsStream( deploymentId, definition.getDiagramResourceName()); //设置bpmn输入 FileOutputStream bpmnOutPut = new FileOutputStream("D:/leave.bpmn"); //设置png输入 FileOutputStream pngOutPut = new FileOutputStream("D:/leave.png"); IOUtils.copy(bpmnInput,bpmnOutPut); IOUtils.copy(pngInput,pngOutPut); }
7.1.3 Удаление определения процесса
- Удалите соответствующее определение процесса на основе идентификатора развертывания.
@Test
public void testDeleteDeploy(){
//流程部署Id
String deploymentId = "10001";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取仓库服务
RepositoryService repositoryService = processEngine.getRepositoryService();
//删除流程定义,如果该流程定义已有流程实例启动则删除时出错
repositoryService.deleteDeployment(deploymentId);
//设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设置为false非级别删除方式,如果流程
//repositoryService.deleteDeployment(deploymentId,true);
}
проиллюстрировать:
-
Если в определении процесса нет запущенного процесса, вы можете использовать обычное удаление.
-
Если в определении процесса уже есть запущенный процесс и при обычном удалении сообщается об ошибке, метод каскадного удаления можно использовать для удаления всех процессов и связанных с ними записей.
-
Операции каскадного удаления во время разработки проекта обычно доступны только суперадминистраторам.
7.2. Связанные с экземпляром процесса
7.2.1 Что такое экземпляр процесса?
Пользователь или программа инициирует процесс в соответствии с содержимым определения процесса, которое является экземпляром процесса.
Иллюстрация определения процесса и экземпляра процесса:
7.2.2 BusinessKey (идентификация бизнеса)
- Сяо Чжан хочет взять отпуск с 1 по 10 мая. Причина отпуска: пойти домой на свидание вслепую.
- Сяо Чэнь хочет взять отпуск с 5 по 15 мая. Причина взять отпуск: его дом сносят, и ему нужно вернуться домой, чтобы пройти формальности.
Сколько экземпляров процесса будет создано?
После запуска процесса в настоящее время назначенным утверждающим отделом является Ли Си. Перед утверждением Ли Си должен узнать время подачи заявления и причину подачи заявления, прежде чем он сможет решить, соглашаться ли.
Так как же информация заявителя об отпуске (время и причина отпуска) связана с процессом?
В это время вам нужно использоватьBusinessKey
- При запуске экземпляра процесса указанный businessKey будет сохранен в таблице act_run_execution.
- BusinessKey: Бизнес-идентификатор, обычно первичный ключ бизнес-таблицы, бизнес-идентификатор и экземпляр процесса имеют однозначное соответствие. Бизнес-идентификатор поступает из бизнес-системы. Хранение бизнес-идентификатора означает сопоставление и запрос данных бизнес-системы на основе бизнес-идентификатора. Например: когда процесс отпуска запускает экземпляр процесса, идентификатор запроса на отпуск может быть сохранен в Activiti в качестве бизнес-идентификатора. В будущем, запросив информацию об экземпляре процесса в Activiti, вы сможете получить идентификатор запроса на отпуск. а затем запросить базу данных бизнес-системы, чтобы получить информацию о запросе на отпуск.
@Test
public void testStartProcess(){
String businessKey = "8001";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RuntimeService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
//根据流程定义的key启动流程实例,这个key是在定义bpmn的时候设置的
//在启动流程的时候将业务key加入进去
ProcessInstance instance = runtimeService
.startProcessInstanceByKey("leaveProcess",businessKey);
//获取流程实例的相关信息
System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
System.out.println("流程实例的id = " + instance.getId());
}
Наблюдая за базой данных, мы можем обнаружить, что в таблице act_ru_execution Activiti в поле BUSINESS_KEY хранится бизнес-КЛЮЧ.
BusinessKey
Как получить и связать соответствующую бизнес-информацию при выполнении пользователями задач ?
@Test
public void testGetBusinessKey(){
//任务负责人
String assignee = "李四";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//获取RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
//获取任务集合
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("leaveProcess")
.taskAssignee(assignee)
.list();
//遍历任务列表
for(Task task:taskList){
System.out.println("流程定义id = " + task.getProcessDefinitionId());
System.out.println("流程实例id = " + task.getProcessInstanceId());
System.out.println("任务id = " + task.getId());
System.out.println("任务名称 = " + task.getName());
//根据任务上的流程实例Id查询出对应的流程实例对象,从流程实例对象中获取BusinessKey
ProcessInstance instance = runtimeService
.createProcessInstanceQuery()
.processInstanceId(task.getProcessInstanceId())
.singleResult();
System.out.println("业务key:"+instance.getBusinessKey());
System.out.println("===================");
}
}
7.2.3 Определение процесса/приостановка/активация экземпляра
Сценарий зависания всех экземпляров процесса :
-
Например, процесс в процессе изменения системы компании, процесс в процессе замены генерального менеджера, в процессе участвуют 100 человек, 70 человек завершили процесс, а процесс из 30 человек находится в процессе изменения. генеральный менеджер, поэтому его нужно приостановить.
-
Например, наш бизнес-процесс:
[Начальный узел]–>[Узел A]–>[Узел B]–>[Узел C]–>[Конечный узел]
Бизнес-логика [узла C] должна взаимодействовать с внешним интерфейсом, и с внешним интерфейсом возникла проблема. Если остальная часть процесса переходит на [узел C] и выполняет бизнес-логику [узла C] , будет сообщено об ошибке. Мы можем Процесс зависает и ожидает доступности внешнего интерфейса, прежде чем повторно активировать процесс.
- Если бизнес-процесс изменится, запущенный экземпляр процесса продолжит следовать старому процессу. Если вновь инициированный процесс будет следовать новому бизнес-процессу. На данный момент нам необходимо приостановить определение процесса, но не экземпляр процесса. .
- Операционный процесс определяется как приостановленный, и все экземпляры процесса, указанные в определении операции, будут приостановлены.
- Определение процесса находится в приостановленном состоянии. Новые экземпляры процесса не смогут запускаться под этим определением процесса. В то же время все экземпляры процесса под этим определением процесса будут приостановлены.
@Test
public void testSuspendAllProcessInstance(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
//获取流程定义对象
ProcessDefinition processDefinition = repositoryService
.createProcessDefinitionQuery()
.processDefinitionKey("leaveProcess")
.singleResult();
boolean suspended = processDefinition.isSuspended();
//输出流程定义状态
System.out.println("流程定义状态:"+(suspended ?"已挂起":"已激活"));
String processDefinitionId = processDefinition.getId();
if(suspended){
//如果是挂起,可以执行激活操作 ,参数1 :流程定义id ,参数2:是否激活流程实例,参数3:激活时间
repositoryService.activateProcessDefinitionById(processDefinitionId,true,null);
System.out.println("流程ID:"+processDefinitionId+",已激活");
}else{
//如果是激活,可以执行挂起操作 ,参数1 :流程定义id ,参数2:是否暂停流程实例,参数3:激活时间
repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
System.out.println("流程ID:"+processDefinitionId+",已挂起");
}
}
- Запросить статус задачи. Если он [Ожидает], администратор не имеет права нажимать кнопку [Обработка задачи].
@Test
public void testSuspendStatus(){
//任务负责人
String assignee = "李四";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//获取任务集合
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("leaveProcess")
.taskAssignee(assignee)
.list();
//遍历任务列表
for(Task task:taskList){
System.out.println("流程定义id = " + task.getProcessDefinitionId());
System.out.println("流程实例id = " + task.getProcessInstanceId());
System.out.println("任务id = " + task.getId());
System.out.println("任务名称 = " + task.getName());
System.out.println("任务状态:"+(task.isSuspended()?"已挂起":"已激活"));
System.out.println("===================");
}
}
-
Используйте предыдущий тестовый пример, чтобы проверить, можно ли запустить новый экземпляр процесса, когда процесс приостановлен.
org.activiti.engine.ActivitiException: Cannot start process instance. Process definition 请假流程 (id = leaveProcess:1:4) is suspended
-
Используйте предыдущий тестовый пример, чтобы проверить, может ли задача быть обработана, когда процесс приостановлен.
org.activiti.engine.ActivitiException: Cannot complete a suspended task
Сценарий зависания одного экземпляра процесса
Процесс подсчета баллов: можно установить многоуровневую подсчет баллов, и процесс подсчета баллов будет оцениваться сверху вниз; оценщик должен завершить выставление оценок в течение установленного срока, в противном случае подсчет очков не будет продолжен, и процесс будет быть приостановлено, и поток остановится;
- Управляйте объектом экземпляра процесса и выполните операцию приостановки для одного процесса. Если экземпляр процесса приостановлен, процесс больше не будет выполняться. При выполнении текущей задачи экземпляра процесса будет сообщено об исключении.
Запросить все экземпляры процессов
@Test
public void testQueryProcessInstance(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RepositoryService
RuntimeService runtimeService = processEngine.getRuntimeService();
List<ProcessInstance> processInstanceList = runtimeService
.createProcessInstanceQuery()
.processDefinitionKey("leaveProcess")
.list();
for(ProcessInstance processInstance:processInstanceList){
System.out.println("流程实例Id:"+processInstance.getId()+",状态:"+(processInstance.isSuspended()?"已挂起":"已激活"));
}
}
Приостановить экземпляр процесса
@Test
public void testSuspendSingleProcessInstance(){
//流程实例Id
String processInstanceId = "2501";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RepositoryService
RuntimeService runtimeService = processEngine.getRuntimeService();
//根据流程实例Id获取流程实例对象
ProcessInstance processInstance = runtimeService
.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
//状态
boolean suspended = processInstance.isSuspended();
System.out.println("流程实例ID:"+processInstanceId+",状态:"+ (suspended?"已挂起":"已激活"));
if(suspended){
runtimeService.activateProcessInstanceById(processInstanceId);
System.out.println("流程实例ID:"+processInstanceId+",状态修改为已激活");
}else{
runtimeService.suspendProcessInstanceById(processInstanceId);
System.out.println("流程实例ID:"+processInstanceId+",状态修改为已挂起");
}
}
7.3 Лицо, ответственное за постановку задач
7.3.1 Фиксированное распределение
-
Назначьте владельцев фиксированных задач при моделировании бизнес-процессов.
7.3.2 Назначение выражения UEL
Activiti использует выражения UEL. UEL является частью спецификации Java EE6. UEL (Unified Expression Language) — это унифицированный язык выражений.
При изменении Правопреемника в плагине actiBPM в IDEA возникает ошибка. Он изменяется в интерфейсе, но сам файл не изменяется. Поэтому нам нужно использовать инструмент редактирования, чтобы изменить Правопреемника в XML-файле.
-
Измените определение процесса и повторно разверните его.
-
Написать лидер конфигурации кода
@Test
public void testStartProcess(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RuntimeService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String,Object> variables = new HashMap<String, Object>();
variables.put("assignee0","zhangsan");
variables.put("assignee1","lisi");
//根据流程定义的key启动流程实例,这个key是在定义bpmn的时候设置的
ProcessInstance instance = runtimeService
.startProcessInstanceByKey("leaveProcess",variables);
//获取流程实例的相关信息
System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
System.out.println("流程实例的id = " + instance.getId());
}
После успешного выполнения вы можете увидеть данные карты прямо сейчас в таблице act_ru_variable.
7.3.3 Распределение слушателей
- Прослушиватели задач выполняют пользовательскую логику или выражения Java при возникновении соответствующих событий, связанных с задачей.
- Мероприятия, связанные с миссией, включают:
- Событие:
- Создать: активируется после создания задачи.
- Назначение: активируется после назначения задачи.
- Удаление: активируется после завершения задачи.
- Все: срабатывает при возникновении всех событий.
- Событие:
-
Настройте класс прослушивателя задач, а затем этот класс должен реализовать интерфейс org.activiti.engine.delegate.TaskListener.
package cn.wolfcode; import org.activiti.engine.delegate.DelegateTask; import org.activiti.engine.delegate.TaskListener; /** * Created by wolfcode */ public class AssigneeTaskListener implements TaskListener { public void notify(DelegateTask delegateTask) { if(delegateTask.getName().equals("部门经理审批")){ delegateTask.setAssignee("赵六"); }else if(delegateTask.getName().equals("部门经理审批")){ delegateTask.setAssignee("孙七"); } } }
-
Настройте прослушиватель в файле bpmn
- В реальной разработке метод выделения слушателей обычно не используется, что слишком хлопотно.
7.4 Переменные процесса
7.4.1 Что такое переменные процесса?
- Переменные процесса играют очень важную роль в Activiti. Для операций процесса иногда требуются переменные процесса. Когда бизнес-система объединяется с Activiti, переменные процесса незаменимы. Переменные процесса — это переменные, которые Activiti устанавливает на основе потребностей управления при управлении рабочими процессами.
- Например, при переносе процесса отпуска, если количество дней отпуска превышает 3 дня, он будет утвержден генеральным директором. В противном случае он будет одобрен непосредственно отделом кадров. Количество дней отпуска может быть установлено как переменная процесса и используется во время передачи процесса.
注意:虽然流程变量中可以存储业务数据,可以通过Activiti的API查询流程变量从而实现查询业务数据,但是不建议这么使用,因为业务数据查询由业务系统负责,Activiti设置流程变量是为了流程执行需要而创建的。
7.4.2 Типы переменных процесса
注意:
如果将POJO存储到流程变量中,必须实现序列化接口Serializable,为了防止由于新增字段无法反序列化。
7.4.3 Область применения переменных процесса
Областью действия переменной процесса может быть экземпляр процесса (ProcessInstance), задача (Task) или экземпляр выполнения (Execution).
- Глобальная переменная: значением по умолчанию области переменной процесса является экземпляр процесса, а область действия является самой большой.
- локальная переменная: если область действия переменной процесса предназначена только для одной задачи или одного экземпляра выполнения, она не такая большая, как область действия экземпляра процесса.
实际开发中一般不用local变量,了解即可.
7.4.4 Как использовать переменные процесса
-
Использование выражений UEL для свойств
Вы можете установить выражение UEL для исполнителя, и значением выражения будет лицо, ответственное за задачу, например: ${назначенный}, назначенный — это имя переменной процесса.
Activiti получает значение выражения UEL, то есть значение назначенного переменной процесса, и использует значение назначенного в качестве лица, ответственного за задачу, для назначения задач.
-
Использование выражений UEL для проводов
Выражения UEL можно задать на линии подключения для определения направления процесса.
Например: ${price<10000}. Цена — это имя переменной процесса, а тип результата выражения uel — логический.
Если выражение UEL истинно, определяется направление выполнения процесса.
7.4.5 Использование глобальных переменных для управления процессом
Требования: Сотрудники создают формы заявлений на отпуск, которые рассматриваются и утверждаются руководителем отдела.После утверждения руководителем отдела отпуск продолжительностью менее 3 дней (включая 3 дня) будет утверждаться непосредственно менеджером по персоналу, а отпуск продолжительностью более 3 дня утверждается генеральным директором, а затем утверждается генеральным директором. Утверждается менеджером по персоналу.
- Добавить условия оценки при соединении
本次画BPMN文件的时候将部门经理的assignee设置为李四,总经理审批的assignee设置为王五,总经理审批的assignee设置为王五,人事复批存档设置为赵六。
package cn.wolfcode.demo;
import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by wolfcode
*/
public class VariablesTest {
/**
* 部署
*/
@Test
public void testDeploy(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/leave-variables.bpmn")
.name("请假流程")
.deploy();
//输出部署的一些信息
System.out.println("流程部署ID:"+deployment.getId());
System.out.println("流程部署名称:"+deployment.getName());
}
@Test
public void testStartProcess(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RuntimeService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String,Object> variables = new HashMap<String,Object>();
variables.put("day",2);
//根据流程定义的key启动流程实例,这个key是在定义bpmn的时候设置的
ProcessInstance instance = runtimeService.startProcessInstanceByKey("leaveVariablesProcess",variables);
//获取流程实例的相关信息
System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
System.out.println("流程实例的id = " + instance.getId());
}
@Test
public void testSelectTodoTaskList(){
//任务负责人
String assignee = "李四";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//获取任务集合
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("leaveVariablesProcess")
.taskAssignee(assignee)
.list();
//遍历任务列表
for(Task task:taskList){
System.out.println("流程定义id = " + task.getProcessDefinitionId());
System.out.println("流程实例id = " + task.getProcessInstanceId());
System.out.println("任务id = " + task.getId());
System.out.println("任务名称 = " + task.getName());
}
}
@Test
public void testCompleteTask(){
//任务负责人
String assignee = "李四";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//获取任务集合
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("leaveVariablesProcess")
.taskAssignee(assignee)
.list();
//遍历任务列表
for(Task task:taskList){
taskService.complete(task.getId());
}
}
}
Что следует отметить :
1.如果UEL表达式中流程变量名不存在则报错。
2.如果如果UEL表达式都不符合条件,流程报错。
3.如果连接不设置条件/条件都满足,每个连线都会走.
7.5 Кандидаты на задание
В определении процесса руководитель задачи фиксируется в назначенном узле задачи, а участники фиксируются в файле .bpmn при определении процесса. Если временный руководитель задачи меняется, определение процесса необходимо изменить, и система имеет плохую масштабируемость.
В этой ситуации для задачи можно задать несколько кандидатов, и из них можно выбрать участников для выполнения задачи.
7.5.1 Установка кандидатов для задач
-
Задайте пользователей-кандидатов (кандидатов) в конфигурации узла задачи на блок-схеме и разделите нескольких кандидатов запятыми.
-
Посмотреть файл bpmn
-
Мы видим, что рецензенты руководителя отдела были назначены группе кандидатов, таких как Лиси и Ванву. Вы можете использовать activiti:candiateUsers="Пользователь 1, Пользователь 2, Пользователь 3", чтобы установить группу кандидатов.
7.5.2 Процесс развертывания и запуска
package cn.wolfcode.demo;
import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by wolfcode
*/
public class CandidateTest {
/**
* 部署
*/
@Test
public void testDeploy(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/leave-candidate.bpmn")
.name("请假流程-候选人")
.deploy();
//输出部署的一些信息
System.out.println("流程部署ID:"+deployment.getId());
System.out.println("流程部署名称:"+deployment.getName());
}
//启动流程
@Test
public void testStartProcess(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RuntimeService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
//根据流程定义的key启动流程实例,这个key是在定义bpmn的时候设置的
ProcessInstance instance = runtimeService.startProcessInstanceByKey("leaveCandidateProcess");
//获取流程实例的相关信息
System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
System.out.println("流程实例的id = " + instance.getId());
}
}
7.5.3 Запрос задач-кандидатов
//查询候选任务
@Test
public void testSelectCandidateTaskList(){
//任务负责人
String candidateUser = "李四";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//获取任务集合
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("leaveCandidateProcess")
.taskCandidateUser(candidateUser)
.list();
//遍历任务列表
for(Task task:taskList){
System.out.println("流程定义id = " + task.getProcessDefinitionId());
System.out.println("流程实例id = " + task.getProcessInstanceId());
System.out.println("任务id = " + task.getId());
System.out.println("任务名称 = " + task.getName());
}
}
7.5.4 Получение заданий кандидатов
@Test
public void testClaimTask(){
//任务ID
String taskId = "2505";
String assignee = "张三";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//领取任务
taskService.claim(taskId,assignee);
}
7.5.4 Выполнение задач
Если задача-кандидат выполнена напрямую без востребования, то пользователь, выполнивший задачу, не будет записан в записи истории.
Итак, для такого рода задач кандидата нам нужно сначала их получить, а затем выполнить.
//执行任务
@Test
public void testCompleteTask(){
//任务ID
String taskId = "2505";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
taskService.complete(taskId);
}
7.6 Шлюз
7.6.1 Эксклюзивный шлюз
Эксклюзивный шлюз (ExclusiveGateway) (шлюз XOR или эксклюзивный шлюз на основе данных), используемый для реализации решений в процессе. Когда процесс выполняется на этом шлюзе, все ветви будут определять, истинно ли условие, и если оно истинно, ветвь будет выполнена.
注意:
排他网关只会选择一个为true的分支执行(即使有两个分支条件都为true,排他网关也只会选择一条分支去执行,选择序号小的路径执行)。
本次画BPMN文件的时候将部门经理的assignee设置为李四,总经理审批的assignee设置为王五,总经理审批的assignee设置为王五,人事复批存档设置为赵六。
package cn.wolfcode.demo;
import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.After;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by wolfcode
*/
public class EGatewayTest {
/**
* 部署
*/
@Test
public void testDeploy(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/leave-EGateway.bpmn")
.name("请假流程-排他网关")
.deploy();
//输出部署的一些信息
System.out.println("流程部署ID:"+deployment.getId());
System.out.println("流程部署名称:"+deployment.getName());
}
@Test
public void testStartProcess(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RuntimeService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String,Object> variables = new HashMap<String,Object>();
variables.put("day",0);
//根据流程定义的key启动流程实例,这个key是在定义bpmn的时候设置的
ProcessInstance instance = runtimeService.startProcessInstanceByKey("leaveEGatewayProcess",variables);
//获取流程实例的相关信息
System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
System.out.println("流程实例的id = " + instance.getId());
}
@Test
public void testCompleteTask(){
//任务负责人
String assignee = "张三";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//获取任务集合
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("leaveEGatewayProcess")
.taskAssignee(assignee)
.list();
//遍历任务列表
for(Task task:taskList){
taskService.complete(task.getId());
}
}
}
7.6.2 Параллельный шлюз
Параллельный шлюз (InclusiveGateway) позволяет разделить процесс на несколько ветвей, а также объединить несколько ветвей.Функция параллельного шлюза основана на входящих и исходящих последовательных потоках.
并行网关不会解析条件。即使顺序流中定义了条件,也会被忽略
本次画BPMN文件的时候将技术经理的assignee设置为李四,项目经理审批的assignee设置为王五,人事复批的assignee设置为王五
package cn.wolfcode.demo;
import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by wolfcode
*/
public class PGatewayTest {
/**
* 部署
*/
@Test
public void testDeploy(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/leave-PGateway.bpmn")
.name("请假流程-并行网关")
.deploy();
//输出部署的一些信息
System.out.println("流程部署ID:"+deployment.getId());
System.out.println("流程部署名称:"+deployment.getName());
}
@Test
public void testStartProcess(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RuntimeService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String,Object> variables = new HashMap<String,Object>();
//根据流程定义的key启动流程实例,这个key是在定义bpmn的时候设置的
ProcessInstance instance = runtimeService.startProcessInstanceByKey("leavePGatewayProcess");
//获取流程实例的相关信息
System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
System.out.println("流程实例的id = " + instance.getId());
}
//完成任务
@Test
public void testCompleteTask(){
//任务负责人
String assignee = "张三";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//获取任务集合
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("leavePGatewayProcess")
.taskAssignee(assignee)
.list();
//遍历任务列表
for(Task task:taskList){
taskService.complete(task.getId());
}
}
}
7.6.3 Включение шлюзов
Инклюзивные шлюзы можно рассматривать как комбинацию эксклюзивных и параллельных шлюзов.
Требования: Заявки на командировку на срок более 3 дней должны быть согласованы с руководителем проекта, на срок менее 3 дней – с техническим руководителем, Заявки на командировку должны быть согласованы с HR Assistant.
本次画BPMN文件的时候将技术经理的assignee设置为张三,项目经理的assignee设置为李四,人事助理的assignee设置为王五,人事复批存档设置为赵六。
package cn.wolfcode.demo;
import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by wolfcode
*/
public class IGatewayTest {
/**
* 部署
*/
@Test
public void testDeploy(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/leave-IGateway.bpmn")
.name("请假流程-包含网关")
.deploy();
//输出部署的一些信息
System.out.println("流程部署ID:"+deployment.getId());
System.out.println("流程部署名称:"+deployment.getName());
}
@Test
public void testStartProcess(){
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RuntimeService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String,Object> variables = new HashMap<String,Object>();
variables.put("day",5);
//根据流程定义的key启动流程实例,这个key是在定义bpmn的时候设置的
ProcessInstance instance = runtimeService.startProcessInstanceByKey("leaveIGatewayProcess",variables);
//获取流程实例的相关信息
System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
System.out.println("流程实例的id = " + instance.getId());
}
//完成任务
@Test
public void testCompleteTask(){
//任务负责人
String assignee = "王五";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//获取任务集合
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("leaveIGatewayProcess")
.taskAssignee(assignee)
.list();
//遍历任务列表
for(Task task:taskList){
taskService.complete(task.getId());
}
}
}