springboot特殊问题处理2——springboot集成flowable实现工作流程的完整教程(一)

本文主要是介绍springboot特殊问题处理2——springboot集成flowable实现工作流程的完整教程(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在实际项目开发过程中,流程相关的业务实现采用工作流会异常清晰明了,但是Activity学习成本和开发难度对追求效率的开发工作者来说异常繁琐,但是作为Activity的亲儿子之一的flowable,其轻量化的使用和对应的api会让开发者感受简单,学习成本很低,值得推荐。

本文案基于springboot2.3.12为例讲解,jdk版本要求至少1.8+,mysql为8.0以上。

一.flowable相关官方网址

官方网站(英文):https://www.flowable.com/

第三方中文用户手册(V6.3.0):https://tkjohn.github.io/flowable-userguide/

二.如何集成springboot

1.引入官方jar或者对应springboot的starter
<dependency><groupId>org.flowable</groupId><artifactId>flowable-spring-boot-starter</artifactId><version>${flowable.version}</version>
</dependency>

我这边根据项目需要只引入相关的flowable-engine

        <dependency><groupId>org.flowable</groupId><artifactId>flowable-engine</artifactId><version>6.3.0</version><exclusions><exclusion><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId></exclusion><exclusion><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></exclusion></exclusions></dependency>
2. 配置项目需要的数据
  • flowable.properties
flowable.url=jdbc:mysql://10.1.0.223:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT&nullCatalogMeansCurrent=true
flowable.username=root
flowable.password=123456
flowable.driverClassName=com.mysql.cj.jdbc.Driver
###生成数据表
flowable.initialize=true
flowable.name=flowable
###动态生成流程执行图(定义中文字体为宋体,防止生成的图片资源存在乱码)
flowable.activityFontName=\u5B8B\u4F53
flowable.labelFontName=\u5B8B\u4F53
flowable.annotationFontName=\u5B8B\u4F53
flowable.xml.encoding=UTF-8
  • 项目结构如下 

  • 测试需要的流程图 

 

三.flowable项目正确开发使用流程

1.首先正确配置flowable.properties该文件,默认在启动项目时会生成34张工作流数据表(均已ACT_开头)

2.利用tomcat启动flowable-admin.war,然后用flowable-ui创建对应的bpm文件(或者其他的bpm工具)

3.调用/deployment这个接口,部署已经写好的流程实例,参数参照后台方法说明传递即可

4.分别查看act_re_deployment,act_re_procdef和act_ge_bytearray数据表,如果生成了相关数据即代表部署成功

5.最后就可以在相关模块创建任务开始动态执行流程

四.flowable流程业务实现以及部分关键代码展示

以下关键代码,需要特意说明的是:

  • ProcessEngine是flowable提供对公开BPM和工作流操作的所有服务的访问关键对象。
  • FlowProcessDiagramGenerator是flowable生成流程实例图片的关键,继承自
    org.flowable.image.impl.DefaultProcessDiagramGenerator类
1.流程部署
    /*** 1.部署流程** @return*/@GetMapping("/deployment")public String deploymentFlowable() {RepositoryService repositoryService = processEngine.getRepositoryService();Deployment deployment = repositoryService.createDeployment().addClasspathResource("flowable_xml/test_flowable.bpmn20.xml")//类别.category("审批类").name("领导审批").deploy();return ResponseResult.ok(deployment);}
2. 查询流程定义
    /*** 2.查询流程定义** @return*/@GetMapping("/queryDeployment")public String queryFlowableDeploy() {RepositoryService repositoryService = processEngine.getRepositoryService();//查询所有定义的流程List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();//查询单个定义的流程/*ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId("5").singleResult();*/
//        System.out.println("Found process definition : " + processDefinition.getName());return ResponseResult.ok(list);}
3.启动流程实例
    /*** 3.启动流程实例** @return*/@RequestMapping("/start/instance")public String startProcessInstance() {RuntimeService runtimeService = processEngine.getRuntimeService();//要启动流程实例,需要提供一些初始化流程变量,自定义Map<String, Object> variables = new HashMap<String, Object>(0);variables.put("employee", "工作组");variables.put("nrOfHolidays", 8);variables.put("description", "请假");ProcessInstance processInstance =runtimeService.startProcessInstanceByKey("leader_approval_key", variables);return ResponseResult.ok(processInstance.getName());}
4.通过流程执行人员查询任务和流程变量
    /*** 通过流程人员定义查询任务和流程变量** @return*/@RequestMapping("/query/task")public String queryProcessInstance() {TaskService taskService = processEngine.getTaskService();//通过组查询任务表
//        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("managers").list();//通过人查询单个任务Task task = taskService.createTaskQuery().taskAssignee("小王").singleResult();//通过任务id查询流程变量Map<String, Object> processVariables = taskService.getVariables(task.getId());return ResponseResult.ok(processVariables);}
5.通过任务id完成任务
    /*** 通过任务id完成任务** @return*/@RequestMapping("/complete/task")public String completeTask(String taskId) {TaskService taskService = processEngine.getTaskService();//领导审批提交的表达信息Map<String, Object> variables = new HashMap<String, Object>(0);taskService.complete(taskId, variables);return ResponseResult.ok();}
 6.通过流程执行人或者审批人查询审批历史记录
    /*** 通过审批人获取历史任务数据** @param name* @return*/@RequestMapping("/history/task")public String getHistoryTask(@RequestParam("name") String name) {HistoryService historyService = processEngine.getHistoryService();//历史任务流程——流程idList<HistoricActivityInstance> activities =historyService.createHistoricActivityInstanceQuery().processInstanceId("2501").finished().orderByHistoricActivityInstanceEndTime().asc().list();//历史任务List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().taskAssignee(name).list();return ResponseResult.ok(list.toString());}
 7.通过流程id查询流程执行图(多种获取方式)
/*** 通过流程id获取流程资源** @return*/@RequestMapping("/process/resource")public void getProcessResource(HttpServletResponse response) throws IOException {RepositoryService repositoryService = processEngine.getRepositoryService();/*ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId("5085").processDefinitionId("defect_report_flowable:1:5088")
//                .processDefinitionKey("leader_approval_key")
//                .deploymentId("5").singleResult();*/BpmnModel bpmnModel = repositoryService.getBpmnModel("defect_report_flowable:1:4");InputStream imageStream = processDiagramGenerator.generateDiagram(bpmnModel);/*String diagramResourceName = processDefinition.getDiagramResourceName();InputStream imageStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), diagramResourceName);*/FileOutputStream fos = new FileOutputStream("D:\\data\\22222.png");byte[] b = new byte[1024];int leng = -1;while ((leng = imageStream.read(b)) != -1) {fos.write(b, 0, leng);}fos.flush();imageStream.close();fos.close();/*//文件流直接写出ByteArrayOutputStream baos = new ByteArrayOutputStream();OutputStream os = response.getOutputStream();int ch = 0;while (-1 != (ch = imageStream.read())) {baos.write(ch);}os.write(baos.toByteArray());imageStream.close();baos.close();os.close();*/}

五.其他相关的功能和问题持续更新,有问题私信 

1.生成流程实例图片的关键代码
@Service
public class FlowProcessDiagramGenerator extends DefaultProcessDiagramGenerator {private static final String IMAGE_TYPE = "png";@Value("${flowable.activityFontName}")private String activityFontName;@Value("${flowable.labelFontName}")private String labelFontName;@Value("${flowable.annotationFontName}")private String annotationFontName;@Value("${flowable.xml.encoding}")private String encoding;@Autowiredprivate ProcessEngine processEngine;/*** 生成执行动态图片流** @param processDefinitionId 流程定义的id——xml文件规固定的key* @param businessKey* @return*/public InputStream generateActiveDiagram(String processDefinitionId, String businessKey) {RuntimeService runtimeService = processEngine.getRuntimeService();HistoryService historyService = processEngine.getHistoryService();RepositoryService repositoryService = processEngine.getRepositoryService();//1.获取当前的流程定义ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processDefinitionId(processDefinitionId)
//                .processInstanceId(processInstanceId).processInstanceBusinessKey(businessKey).singleResult();//流程实例执行的实例idString processId = null;List<String> activeActivityIds = new ArrayList<>();List<String> highLightedFlows = new ArrayList<>();//3. 获取流程定义id和高亮的节点idif (processInstance != null) {//3.1. 正在运行的流程实例processId = processInstance.getProcessInstanceId();//2.获取所有的历史轨迹线对象List<HistoricActivityInstance> historicSquenceFlows = historyService.createHistoricActivityInstanceQuery()
//                .processDefinitionId(processInstanceId).processInstanceId(processId).activityType(BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW).list();historicSquenceFlows.forEach(historicActivityInstance -> highLightedFlows.add(historicActivityInstance.getActivityId()));activeActivityIds = runtimeService.getActiveActivityIds(processId);} else {//3.2. 已经结束的流程实例HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processDefinitionId(processDefinitionId)
//                    .processInstanceId(processId).processInstanceBusinessKey(businessKey).singleResult();if(historicProcessInstance == null){throw new MessageCodeException(MessageCode.FLOWABLE_PROCESS_IS_RELEASE_SUCCESS);}processId = historicProcessInstance.getId();//3.3. 获取结束节点列表List<HistoricActivityInstance> historicEnds = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).activityType(BpmnXMLConstants.ELEMENT_EVENT_END).list();List<String> finalActiveActivityIds = activeActivityIds;historicEnds.forEach(historicActivityInstance -> finalActiveActivityIds.add(historicActivityInstance.getActivityId()));}//4. 获取bpmnModel对象BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);//模型 活动节点 高亮线return generateDiagram(bpmnModel, IMAGE_TYPE, activeActivityIds,highLightedFlows, activityFontName, labelFontName, annotationFontName,null, 1.0);}/*** 生成工作流程图** @param bpmnModel 模型* @return*/public InputStream generateDiagram(BpmnModel bpmnModel) {return generateDiagram(bpmnModel, IMAGE_TYPE, activityFontName,labelFontName, annotationFontName,null, 1.0);}

这篇关于springboot特殊问题处理2——springboot集成flowable实现工作流程的完整教程(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1085272

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关