Flowable — это легковесный движок рабочих процессов, написанный на Java. Он удобен для быстрого развития и легко интегрируется с различными фреймворками, такими как Spring Boot. Если проект требует быстрой реализации функциональности рабочих процессов, то использование этого фреймворка будет отличным выбором.
Flowable поддерживает три различных типа движков рабочих процессов: BPMN для управления процессами, CMMN для управления случаями и DMN для управления правилами принятия решений.
act_cmmn_
: данные для движка CMMN (case management model and notation).
act_dmn_
: данные для движка DMN (decision model and notation).
act_evt_log
: лог событий.
act_fo_
: данные для движка форм (forms).
act_ge_
: общие данные (general), используемые во всех случаях.
act_hi_
: таблицы, содержащие исторические данные (history), такие как прошлые экземпляры процессов, переменные, задачи и т.д.
act_id_
: данные, связанные с аутентификацией пользователя (identity).
act_prodef_info
: информация о определении процесса.
act_re_
: данные для репозитория определений процессов (repository). Таблицы с этим префиксом содержат статическую информацию, такую как определение процесса и ресурсы процесса (изображения, правила и т.д.).act_ru_
: данные, используемые при выполнении процесса (runtime). Это таблицы, содержащие информацию, такую как экземпляры процесса, пользовательские задачи, переменные, задания и т.д., которые используются во время выполнения процесса. Flowable хранит эти данные только во время выполнения процесса и удаляет записи после завершения процесса. Это позволяет поддерживать размер и скорость этих таблиц небольшими.
TENANT_ID_ (tenantId) — это значение, которое используется для отслеживания того, к какому системному контексту относится запущенный экземпляр процесса. Например, если три системы (A, B и C) имеют одинаковый процесс запроса отпуска и все они используют одну и ту же базу данных, то этот параметр поможет разделить эти процессы.
Различные способы развертывания документов процесса:
DeploymentBuilder addInputStream(String resourceName, InputStream inputStream);
DeploymentBuilder addClasspathResource(String resource);
DeploymentBuilder addString(String resourceName, String text);
DeploymentBuilder addBytes(String resourceName, byte[] bytes);
DeploymentBuilder addZipInputStream(ZipInputStream zipInputStream);
DeploymentBuilder addBpmnModel(String resourceName, BpmnModel bpmnModel);
```#### 3.1.1 Метод addInputStream
@Test
public void addInputStreamTest() throws IOException {
// Чтение входящего потока данных о файле
InputStream inputStream = DeploymentBuilderTest.class.getClassLoader()
.getResource("com/shareniu/shareniu_flowable6/ch2/leave.bpmn")
.openStream();
// Установка категории определения процесса
String category = "shareniu_addInputStream";
// Создание объекта DeploymentBuilder
DeploymentBuilder deploymentBuilder = repositoryService
.createDeployment().category(category)
.addInputStream(resourceName, inputStream);
// Развертывание
Deployment deploy = deploymentBuilder.deploy();
System.out.println(deploy);
}#### 3.1.2 метод addClasspathResource
public void addClasspathResource() throws InterruptedException {
ProcessEngineConfigurationImpl processEngineConfiguration = Context
.getProcessEngineConfiguration();
System.out.println(processEngineConfiguration);
String resource = "com/shareniu/chapter3/common.bpmn";
// Классификация определения процесса
String category = "shareniu_addClasspathResource";
// Создание объекта DeploymentBuilder
Date date = new Date();
DeploymentBuilder deploymentBuilder = repositoryService
.createDeployment()
// .activateProcessDefinitionsOn(date)
.addClasspathResource(resource).category(category);
// Развертывание
processEngineConfiguration = Context.getProcessEngineConfiguration();
System.out.println(processEngineConfiguration);
Deployment deploy = deploymentBuilder.deploy();
System.out.println(deploy);
}
#### 3.1.3 метод addString
@Test
public void addString() {
String resource = "shareniu_addString.bpmn";
// Чтение файла для получения XML-определения в файле
String text = readTxtFile("E:/activitilearning/activiti/src/main/java/com/shareniu/chapter3/common.bpmn");
// Создание объекта DeploymentBuilder
DeploymentBuilder deploymentBuilder = repositoryService
.createDeployment().addString(resource, text);
// Развертывание
Deployment deploy = deploymentBuilder.deploy();
}
```#### 3.1.4 метод addZip
@Test
public void zip() {
InputStream inputStream = DeploymentBuilderTest.class.getClassLoader()
.getResourceAsStream("1.zip");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
Deployment deploy = repositoryService.createDeployment()
.addZipInputStream(zipInputStream).deploy();
identityService.setAuthenticatedUserId("shareniu");
}#### 3.1.5 метод addByte
Этот метод позволяет непосредственно преобразовать строку в массив байтов для развертывания.#### 3.1.6 Метод `BpmnModel`
```java
SequenceFlow flow1 = new SequenceFlow();
flow1.setId("flow1");
flow1.setName("начальный узел -> задача 1");
flow1.setSourceRef("start1");
flow1.setTargetRef("userTask1");
// задача 1 -> задача 2
SequenceFlow flow2 = new SequenceFlow();
flow2.setId("flow2");
flow2.setName("задача 1 -> задача 2");
flow2.setSourceRef("userTask1");
flow2.setTargetRef("userTask2");
// задача 2 -> конечный узел
SequenceFlow flow3 = new SequenceFlow();
flow3.setId("flow3");
flow3.setName("задача 2 -> конечный узел");
flow3.setSourceRef("userTask2");
flow3.setTargetRef("endEvent");
String resource = "shareniu_addBpmnModel";
// объявление объекта BpmnModel
BpmnModel bpmnModel = new BpmnModel();
// объявление объекта Process; один объект BpmnModel может содержать несколько объектов Process
Process process = new Process();
process.setId("process1");
// упаковка начального узла
StartEvent start = new StartEvent();
start.setName("начальный узел");
start.setId("start1");
start.setOutgoingFlows(Arrays.asList(flow1));
// задача 1
UserTask userTask1 = new UserTask();
userTask1.setName("задача 1");
userTask1.setId("userTask1");
userTask1.setIncomingFlows(Arrays.asList(flow1));
userTask1.setOutgoingFlows(Arrays.asList(flow2));
// задача 2
UserTask userTask2 = new UserTask();
userTask2.setName("задача 2");
userTask2.setId("userTask2");
userTask2.setIncomingFlows(Arrays.asList(flow2));
userTask2.setOutgoingFlows(Arrays.asList(flow3));
// конечный узел
EndEvent endEvent = new EndEvent();
endEvent.setName("конечный узел");
endEvent.setId("endEvent");
endEvent.setIncomingFlows(Arrays.asList(flow3));
// добавление всех FlowElement в процесс
process.addFlowElement(start);
process.addFlowElement(flow1);
process.addFlowElement(userTask1);
process.addFlowElement(flow2);
process.addFlowElement(userTask2);
process.addFlowElement(flow3);
process.addFlowElement(endEvent);
bpmnModel.addProcess(process);
repositoryService
:主要用于管理流程部署的数据 → repositoryService
:主要用于管理流程部署的数据
Также следует отметить, что фраза "主要用于管理流程部署的数据" уже переведена на русский язык, поэтому нет необходимости делать повторный перевод.runtimeService
:主要用于管理流程在运行时产生的数据(流程参数、事件、流程实例及执行流)以及对正在运行的流程进行操作的API#### 3.2.1 Базовое использование
String processDefinitionId = "myProcess:1:9527"; // ID процесса, который был развернут
runtimeService.startProcessInstanceById(processDefinitionId); // Запуск процесса
Authentication.setAuthenticatedUserId("Foolish");
String processDefinitionId = "myProcess:1:9527";
runtimeService.startProcessInstanceById(processDefinitionId);
Authentication.setAuthenticatedUserId(null);
Прежде всего, метод Authentication.setAuthenticatedUserId
используется для установки аутентифицированного пользователя.
Обратите внимание: этот метод использует переменную типа ThreadLocal
для хранения данных, то есть данные привязываются к текущему потоку. Поэтому после завершения запуска экземпляра процесса его значение должно быть установлено в null
, чтобы избежать проблем при работе с многопоточностью.
После выполнения вышеуказанного кода поле START_USER_ID_
таблицы act_hi_procinst
будет содержать значение "Foolish"
.
public GritResult instanceList(String userId) {
ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery();
if (!StringUtils.isEmpty(userId)) {
query.startedBy(userId);
}
List<ProcessInstance> processInstanceList = query.list();
}
public GritResult taskList(String userId, String group) {
TaskQuery query = taskService.createTaskQuery();
if (!StringUtils.isEmpty(group)) {
query.taskCandidateGroup("managers");
} else if (!StringUtils.isEmpty(userId)) {
query.taskCandidateOrAssigned(userId);
}
} List<Task> tasks = query.orderByTaskCreateTime().desc().list();
}
Поиск исторических экземпляров процесса
public GritResult historicTaskList(String userId) {
HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery();
if (!StringUtils.isEmpty(userId)) {
query.involvedUser(userId);
}
query.finished();
List<HistoricProcessInstance> hpis = query.orderByProcessInstanceEndTime().desc().list();
List<HistoricProcessInstance_> list = new ArrayList<>();
for (HistoricProcessInstance hpi : hpis) {
HistoricProcessInstance_ ft = new HistoricProcessInstance_(hpi);
System.out.println(ft.toString());
list.add(ft);
}
GritResult gr = new GritResult("success", list.size(), list);
return gr;
}
```### 3.4 Проверка согласования
Здесь приведены простые примеры, в которых путь дальнейшего выполнения процесса контролируется параметром **outcome**, установленным в конфигурации.
```java
/**
* Подтверждение
*
* @param taskId ID задачи
*/
public String approve(String taskId) {
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
throw new RuntimeException("Задача не найдена");
}
// Принятие решения
HashMap<String, Object> map = new HashMap<>();
map.put("outcome", "Принять");
taskService.complete(taskId, map);
return "обработано успешно!";
}
/**
* Отклонение
*/
public String reject(String taskId) {
HashMap<String, Object> map = new HashMap<>();
map.put("outcome", "Отклонить");
taskService.complete(taskId, map);
return "отклонено";
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )