springboot-flowable — это решение для быстрого создания рабочих процессов.
springboot + flowable
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- зависимости для работы с flowable -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.3.0</version>
</dependency>
<!-- зависимости для работы с MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
</dependencies>
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/flowable-spring-boot?characterEncoding=UTF-8
username: root
password: root
flowable:
# Отключение асинхронного выполнения задач JOB
async-executor-activate: false
После выполнения этих шагов, интеграция flowable и springBoot будет завершена!
Затем вы можете запустить приложение. При первом запуске flowable автоматически выполнит инициализирующие скрипты, создав необходимые таблицы для работы с рабочими процессами. Если в указанной базе данных еще нет таблиц flowable, они будут созданы.## Определение файлов процесса ExpenseProcess. bpmn20. xml~~~xml
Процесс подачи заявки на возмещение затрат 500}]]> ~~~ Вот перевод текста на русский язык:Вот текст с исправлениями: Вот два агента, используемых в классах: ~~~java import org.flowable.engine.delegate.TaskListener; import org.flowable.task.service.delegate.DelegateTask; public class ManagerTaskHandler implements TaskListener { @Override public void notify(DelegateTask delegateTask) { delegateTask.setAssignee("Менеджер"); } } ~~~ ~~~java public class BossTaskHandler implements TaskListener { @Override public void notify(DelegateTask delegateTask) { delegateTask.setAssignee("Босс"); } } ~~~ Хотя BPMN-файл и является довольно большим, не стоит беспокоиться, так как он был сгенерирован с помощью соответствующих инструментов. Основная логика, как правило, находится в теге process. Для более подробного понимания можно изучить теги BPMN. В документации Flowable также есть соответствующие описания, см. раздел "Creating a ProcessEngine". ---  #### Таким образом, при запуске этого фреймворка он по умолчанию загружает конфигурацию процессов из директории resource и сохраняет её в базе данных для дальнейшего использования. # Тестовый контроллер Для удобства здесь используется контроллер для быстрого создания этого демонстрационного примера. ~~~java @Controller @RequestMapping(value = "/expense") public class ExpenseController { @Autowired private RuntimeService runtimeService; @Autowired private TaskService taskService; @Autowired private RepositoryService repositoryService; @Autowired private ProcessEngine processEngine; /*************** Здесь находится бизнес-логика ******************/ } ~~~~~~java /** * Добавление расхода * * @param userId Идентификатор пользователя * @param money Сумма расхода * @param description Описание */ @RequestMapping(value = "add") @ResponseBody public String addExpense(String userId, Integer money, String description) { // Запуск процесса HashMap map = new HashMap<>(); map.put("taskUser", userId); map.put("money", money); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("Expense", map); return "Сообщение отправлено успешно. Идентификатор процесса: " + processInstance.getId(); } ~~~~~~java /** * Получить список управления утверждениями */ @RequestMapping(value = "/list") @ResponseBody public Object list(String userId) { List tasks = taskService.createTaskQuery().taskAssignee(userId).orderByTaskCreateTime().desc().list(); for (Task task : tasks) { System.out.println(task.toString()); } return tasks.toArray().toString(); } ~~~~~~java /** * Утверждение * * @param taskId идентификатор задачи */ @RequestMapping(value = "apply") @ResponseBody public String apply(String taskId) { Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); if (task == null) { throw new RuntimeException("Процесс не существует"); } // Принятие решения HashMap map = new HashMap<>(); map.put("outcome", "Принято"); taskService.complete(taskId, map); return "обработано успешно!"; } ~~~~~~java /** * Отклонение */ @ResponseBody @RequestMapping(value = "reject") public String reject(String taskId) { HashMap map = new HashMap<>(); map.put("outcome", "Отклонено"); taskService.complete(taskId, map); return "отклонено"; } ~~~~~~java /** * Генерация схемы процесса * * @param processId Идентификатор процесса */ @RequestMapping(value = "processDiagram") public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception { ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult(); // Если процесс завершен, схема не отображается if (pi == null) { return; } Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult(); // Используем идентификатор процесса для поиска активного экземпляра процесса String instanceId = task.getProcessInstanceId(); List executions = runtimeService .createExecutionQuery() .processInstanceId(instanceId) .list(); // Получаем активные идентификаторы Activity List activityIds = new ArrayList<>(); List flows = new ArrayList<>(); for (Execution exe : executions) { List ids = runtimeService.getActiveActivityIds(exe.getId()); activityIds.addAll(ids); } // Получаем схему процесса BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId()); ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration(); ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator(); InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0); OutputStream out = null; byte[] buf = new byte[1024]; int length = 0; try { out = httpServletResponse.getOutputStream(); while ((legth = in.read(buf)) != -1) { out.write(buf, 0, legth); } } finally { if (in != null) { in.close(); } if (out != null) { out.close(); } } } ~~~На основе переданного идентификатора процесса генерируется схема текущего процесса для фронтенда. Если в процессе используются китайские символы и сгенерированное изображение отображается как набор случайных символов, необходимо настроить шрифт:~~~java /** * @author haiyangp * date: 2018/4/7 * desc: конфигурация Flowable — для решения проблемы отображения китайских символов как набора случайных символов */ @Configuration public class FlowableConfig implements EngineConfigurationConfigurer { @Override public void configure(SpringProcessEngineConfiguration engineConfiguration) { engineConfiguration.setActivityFontName("宋体"); engineConfiguration.setLabelFontName("宋体"); engineConfiguration.setAnnotationFontName("宋体"); } } ~~~ #### Тестовый запрос 1. Запустите проект, затем создайте процесс: Посетите: http://localhost:8080/expense/add?userId=123&money=123321 Ответ: Подача успешно завершена. Идентификатор процесса: 2501 2. Проверьте список задач: Посетите: http://localhost:8080/expense/list?userId=123 Ответ: Task[id=2507, name=出差报销] 3. Подтвердите: ==Обратите внимание: передаются taskid== Посетите: http://localhost:8080/expense/apply?taskId=2507 Ответ: processed ok! 4. Генерация схемы процесса: Посетите: http://localhost:8080/expense/processDiagram?processId=2501  #### Участие в проекте 1. Fork этого репозитория 2. Создайте ветку Feat_xxx 3. Подайте пулл-запрос #### Особенности Gitee 1. Запустите проект, затем создайте процесс: Посетите: http://localhost:8080/expense/add?userId=123&money=123321 Ответ: Подача успешно завершена. Идентификатор процесса: 2501 2. Проверьте список задач: Посетите: http://localhost:8080/expense/list?userId=123 Ответ: Task[id=2507, name=出差报销] 3. Подтвердите: ==Обратите внимание: передаются taskid== Посетите: http://localhost:8080/expense/apply?taskId=2507 Ответ: processed ok! 4. Генерация схемы процесса: Посетите: http://localhost:8080/expense/processDiagram?processId=2501  #### Участие в проекте 1. Fork этого репозитория 2. Создайте ветку Feat_xxx 3. Подайте пулл-запрос #### Особенности Gitee1. Используйте Readme_XXX.md для поддержки различных языков, например Readme_en.md, Readme_zh.md 2. Официальный блог Gitee [blog.gitee.com](https://blog.gitee.com) 3. Вы можете посетить [https://gitee.com/explore](https://gitee.com/explore) для изучения лучших открытых проектов на Gitee 4. [GVP](https://gitee.com/gvp) — это сокращение от "Gitee Most Valuable Projects", что означает лучшие проекты, оцененные командой Gitee 5. Официальная документация Gitee [https://gitee.com/help](https://gitee.com/help) 6. Секция "лица Gitee" представляет лучших участников Gitee [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )