Второй рабочий процесс Activiti7 [начальная запись Activiti7, расширенная версия 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 . Затем мы экспортируем его как файлbpmnpngpngbpmnpng

  • Переименуйте 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);
}

проиллюстрировать:

  1. Если в определении процесса нет запущенного процесса, вы можете использовать обычное удаление.

  2. Если в определении процесса уже есть запущенный процесс и при обычном удалении сообщается об ошибке, метод каскадного удаления можно использовать для удаления всех процессов и связанных с ними записей.

  3. Операции каскадного удаления во время разработки проекта обычно доступны только суперадминистраторам.

7.2. Связанные с экземпляром процесса

7.2.1 Что такое экземпляр процесса?

Пользователь или программа инициирует процесс в соответствии с содержимым определения процесса, которое является экземпляром процесса.

Иллюстрация определения процесса и экземпляра процесса:

Вставьте сюда описание изображения

7.2.2 BusinessKey (идентификация бизнеса)

  1. Сяо Чжан хочет взять отпуск с 1 по 10 мая. Причина отпуска: пойти домой на свидание вслепую.
  2. Сяо Чэнь хочет взять отпуск с 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 Определение процесса/приостановка/активация экземпляра

Сценарий зависания всех экземпляров процесса :

  1. Например, процесс в процессе изменения системы компании, процесс в процессе замены генерального менеджера, в процессе участвуют 100 человек, 70 человек завершили процесс, а процесс из 30 человек находится в процессе изменения. генеральный менеджер, поэтому его нужно приостановить.

  2. Например, наш бизнес-процесс:

[Начальный узел]–>[Узел A]–>[Узел B]–>[Узел C]–>[Конечный узел]

Бизнес-логика [узла C] должна взаимодействовать с внешним интерфейсом, и с внешним интерфейсом возникла проблема. Если остальная часть процесса переходит на [узел C] и выполняет бизнес-логику [узла C] , будет сообщено об ошибке. Мы можем Процесс зависает и ожидает доступности внешнего интерфейса, прежде чем повторно активировать процесс.

  1. Если бизнес-процесс изменится, запущенный экземпляр процесса продолжит следовать старому процессу. Если вновь инициированный процесс будет следовать новому бизнес-процессу. На данный момент нам необходимо приостановить определение процесса, но не экземпляр процесса. .
  • Операционный процесс определяется как приостановленный, и все экземпляры процесса, указанные в определении операции, будут приостановлены.
  • Определение процесса находится в приостановленном состоянии. Новые экземпляры процесса не смогут запускаться под этим определением процесса. В то же время все экземпляры процесса под этим определением процесса будут приостановлены.
@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 при возникновении соответствующих событий, связанных с задачей.
  • Мероприятия, связанные с миссией, включают:
    • Событие:
      • Создать: активируется после создания задачи.
      • Назначение: активируется после назначения задачи.
      • Удаление: активируется после завершения задачи.
      • Все: срабатывает при возникновении всех событий.
  1. Настройте класс прослушивателя задач, а затем этот класс должен реализовать интерфейс 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("孙七");
            }
        }
    }
    
  2. Настройте прослушиватель в файле 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());
        }
    }
}

Supongo que te gusta

Origin blog.csdn.net/m0_52896752/article/details/133205567
Recomendado
Clasificación