工作流:一文让你学会使用flowable工作流

工作流:一文让你学会使用flowable工作流1 环境参考 flowable 官方手册 https tkjohn github io flowable userguide 2 对代码进行讲解 packagecom example flowable holiday importorg flowable engine importorg flowable engine impl cfg StandalonePr importorg flowable engine repositor

1.请假流程图

在这里插入图片描述

2.工作流文件

holiday-request.bpmn20.xml

 
    <definitions xmlns="http://www.omg.org/spec/BPMN//MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:bpmndi="http://www.omg.org/spec/BPMN//DI" xmlns:omgdc="http://www.omg.org/spec/DD//DC" xmlns:omgdi="http://www.omg.org/spec/DD//DI" xmlns:flowable="http://flowable.org/bpmn" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef"> <process id="holidayRequest" name="Holiday Request" isExecutable="true"> <startEvent id="startEvent"/> <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/> <userTask id="approveTask" name="Approve or reject request" flowable:candidateGroups="managers"/> <sequenceFlow sourceRef="approveTask" targetRef="decision"/> <exclusiveGateway id="decision"/> <sequenceFlow sourceRef="decision" targetRef="externalSystemCall"> <conditionExpression xsi:type="tFormalExpression">  ${approved}   
     conditionExpression>  
      sequenceFlow> <sequenceFlow sourceRef="decision" targetRef="sendRejectionMail"> <conditionExpression xsi:type="tFormalExpression">  ${!approved}   
       conditionExpression>  
        sequenceFlow> <serviceTask id="externalSystemCall" name="Enter holidays in external system" flowable:class="com.example.flowable.holiday.CallExternalSystemDelegate"/> <sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/> <userTask id="holidayApprovedTask" name="Holiday approved" flowable:assignee="${employee}"/> <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/> <serviceTask id="sendRejectionMail" name="Send out rejection email" flowable:class="com.example.flowable.holiday.SendRejectionMail"/> <sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/> <endEvent id="approveEnd"/> <endEvent id="rejectEnd"/>  
         process>  
          definitions> 

3.pom文件

依赖的jar包如下:

<dependency> <groupId>org.flowable 
     groupId> <artifactId>flowable-engine 
      artifactId> <version>6.4.2 
       version>  
        dependency> <dependency> <groupId>com.h2database 
         groupId> <artifactId>h2 
          artifactId> <scope>runtime 
           scope>  
            dependency> <dependency> <groupId>mysql 
             groupId> <artifactId>mysql-connector-java 
              artifactId> <scope>runtime 
               scope>  
                dependency> <dependency> <groupId>org.projectlombok 
                 groupId> <artifactId>lombok 
                  artifactId> <optional>true 
                   optional>  
                    dependency> <dependency> <groupId>org.springframework.boot 
                     groupId> <artifactId>spring-boot-starter-test 
                      artifactId> <scope>test 
                       scope>  
                        dependency> <dependency> <groupId>org.slf4j 
                         groupId> <artifactId>slf4j-api 
                          artifactId> <version>1.7.21 
                           version>  
                            dependency> <dependency> <groupId>org.slf4j 
                             groupId> <artifactId>slf4j-log4j12 
                              artifactId> <version>1.7.21 
                               version>  
                                dependency> 

2.源码

(1)HolidayRequest类为测试主类

 package com.example.flowable.holiday; import org.flowable.engine.*; import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration; import org.flowable.engine.repository.Deployment; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.engine.task.Comment; import org.flowable.task.api.Task; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Scanner; / 1. 此类描述的是:测试demo 2. 参考flowable手册https://tkjohn.github.io/flowable-userguide/ 3. @author juge 4. @version 2021/9/9 9:54 */ public class HolidayRequest { 
    public static void main(String[] args) { 
    //1.创建一个独立(standalone)配置 ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration() /*.setJdbcUrl("jdbc:h2:mem:flowable;DB_CLOSE_DELAY=-1") .setJdbcUsername("sa") .setJdbcPassword("") .setJdbcDriver("org.h2.Driver")*/ .setJdbcUrl("jdbc:mysql://127.0.0.1:3306/flowable?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true") .setJdbcUsername("root") .setJdbcPassword("") .setJdbcDriver("com.mysql.jdbc.Driver") //如果数据表不存在的时候,自动创建数据表 .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); //2.创建流程引擎 ProcessEngine processEngine = cfg.buildProcessEngine(); // 使用BPMN 2.0定义process。存储为XML,同时也是可以可视化的。NPMN 2.0标准可以让技术人员与业务人员都参与讨论业务流程中来 //3.利用流程引擎部署流程 RepositoryService repositoryService = processEngine.getRepositoryService(); Deployment deployment = repositoryService.createDeployment() .addClasspathResource("holiday-request.bpmn20.xml") .deploy(); //4.根据流程部署实例id获取流程定义实例 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .deploymentId(deployment.getId()) .singleResult(); System.out.println("Found process definition : " + processDefinition.getName()); //5.启动process实例 //5.1需要一些初始化的变量,这里我们简单的从Scanner中获取,一般在线上会通过接口传递过来(发起流程的表单) //5.1.1 scanner输入类似于web前端表单输入 Scanner scanner= new Scanner(System.in); System.out.println("Who are you?"); String employee = scanner.nextLine(); System.out.println("How many holidays do you want to request?"); Integer nrOfHolidays = Integer.valueOf(scanner.nextLine()); System.out.println("Why do you need them?"); String description = scanner.nextLine(); //5.1.2 此处代码类似web后端获取前端表单传来的字段 Map<String, Object> variables = new HashMap<String, Object>(); variables.put("employee", employee); variables.put("nrOfHolidays", nrOfHolidays); variables.put("description", description); //6.发起流程 RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holidayRequest", variables); //7.经理查询待办任务 TaskService taskService = processEngine.getTaskService(); /*将第一个任务指派给"经理(managers)"组,而第二个用户任务指派给请假申请的提交人。因此需要为第一个任务添加candidateGroups属性: 
    这里的candidateGroups,中文一般成为候选组,实际是一组用户的带号,在实际使用中可以写用户的角色id,或者组织机构(岗位、职位)id等 当用户查看待办列表时,后台根据用户的id查询角色id,然后用角色id替换managers即可查询到对应的任务列表 */ List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("managers").list(); //8.经理处理审批任务 //实际一般为用户在web前端页面的待办任务列表,此处演示为控制台输入输出人机交互 System.out.println("You have " + tasks.size() + " tasks:"); for (int i=0; i<tasks.size(); i++) { 
    System.out.println((i+1) + ") " + tasks.get(i).getName()); } System.out.println("Which task would you like to complete?"); //8.1 选择要处理的任务 //此处一般为web前端页面,点击“同意”或“驳回”的按钮,同意为"y",驳回为"n" int taskIndex = Integer.valueOf(scanner.nextLine()); Task task = tasks.get(taskIndex - 1); //使用任务Id获取特定流程实例的变量 Map<String, Object> processVariables = taskService.getVariables(task.getId()); System.out.println(processVariables.get("employee") + " wants " + processVariables.get("nrOfHolidays") + " of holidays. Do you approve this?"); //8.2 编写任务处理意见,并进行approved or rejected的操作 //此处一般为web前端页面,点击“同意”或“驳回”的按钮,同意为"y",驳回为"n" boolean approved = scanner.nextLine().toLowerCase().equals("y"); //8.3 完成任务 //此处代码一般写在web后端,接收到前端的同意或驳回的参数,完成任务 variables = new HashMap<String, Object>(); variables.put("approved", approved); //注意先保存意见,再完成任务,否则任务完成后找不到 if (approved){ 
    Comment comment = taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), "同意休假"); comment.setUserId("manager"); taskService.saveComment(comment); }else{ 
    Comment comment = taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), "不允许休假"); comment.setUserId("manager"); taskService.saveComment(comment); } taskService.complete(task.getId(), variables); //9.申请人查询待办事务 /*并如下所示为第二个任务添加assignee属性。请注意我们没有像上面的’managers’一样使用静态值,而是使用一个流程变量动态指派。这个流程变量是在流程实例启动时传递的: 
    */ //注意发起流程时的employee,最好为申请人或者审批人的id或其他唯一字段 tasks = taskService.createTaskQuery().taskAssignee(employee).list(); //10.申请人处理休假任务 System.out.println("You have " + tasks.size() + " tasks:"); for (int i=0; i<tasks.size(); i++) { 
    System.out.println((i+1) + ") " + tasks.get(i).getName()); } if (tasks.size() > 0){ 
    System.out.println("Which task would you like to complete?"); //10.1 选择要处理的任务 taskIndex = Integer.valueOf(scanner.nextLine()); task = tasks.get(taskIndex - 1); //使用任务Id获取特定流程实例的变量 processVariables = taskService.getVariables(task.getId()); System.out.println("Hi " + processVariables.get("employee") + "please use your holidays !"); //10.2 完成任务 variables = new HashMap<String, Object>(); Comment comment1 = taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), processVariables.get("employee") + "休假中"); comment1.setUserId("employe"); taskService.saveComment(comment1); taskService.complete(task.getId(), variables); } //展示审批意见 List<Comment> taskComments = taskService.getProcessInstanceComments(processInstance.getProcessInstanceId()); for (Comment comment:taskComments){ 
    System.out.println("审批人:"+comment.getUserId() + ",审批意见:" + comment.getFullMessage() + ",审批时间:" + comment.getTime()); } //展示流程流转的历史记录 /*HistoryService historyService = processEngine.getHistoryService(); List 
   
     activities = historyService.createHistoricActivityInstanceQuery() .processInstanceId(processInstance.getId()) .finished() .orderByHistoricActivityInstanceEndTime().asc() .list(); for (HistoricActivityInstance activity : activities) { System.out.println(activity.getActivityId() + " took " + activity.getDurationInMillis() + " milliseconds"); }*/ 
    } } 

(2)CallExternalSystemDelegate类为Enter holidays in external system事件的执行类

package com.example.flowable.holiday; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.JavaDelegate; public class CallExternalSystemDelegate implements JavaDelegate { 
    @Override public void execute(DelegateExecution delegateExecution) { 
    System.out.println("Calling the external system for employee " + delegateExecution.getVariable("employee")); } } 

(3)SendRejectionMail类为Send out rejection email事件的执行类

ackage com.example.flowable.holiday; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.JavaDelegate; public class SendRejectionMail implements JavaDelegate { 
    @Override public void execute(DelegateExecution delegateExecution) { 
    System.out.println("send e-mail to employee " + delegateExecution.getVariable("employee")); } } 

3.测试

启动HolidayRequest类进行测试,控制台日志如下:

Found process definition : Holiday Request Who are you? john How many holidays do you want to request? 2 Why do you need them? go to ... You have 3 tasks: 1) Approve or reject request 2) Approve or reject request 3) Approve or reject request Which task would you like to complete? 3 john wants 2 of holidays. Do you approve this? y Calling the external system for employee john You have 1 tasks: 1) Holiday approved Which task would you like to complete? 1 Hi johnplease use your holidays ! 审批人:employe,审批意见:john休假中,审批时间:Thu Sep 09 15:13:51 CST 2021 审批人:manager,审批意见:同意休假,审批时间:Thu Sep 09 15:13:47 CST 2021 

4 说明

一般工作流使用的是web方式,web前端页面输入,后端进行逻辑处理并输出到前端页面展示。HolidayRequest类中的demo,输入采用scanner,控制台代替web前端页面。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/212363.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午8:13
下一篇 2026年3月18日 下午8:13


相关推荐

  • ES6数组方法find()、findIndex()的总结「建议收藏」

    ES6数组方法find()、findIndex()的总结「建议收藏」本文主要讲解ES6数组方法find()与findIndex(),关于JS的更多数组方法,可参考以下:①JavaScript内置对象之-Array②ES5新增数组方法(例:map()、indexOf()、filter()等)③ES6新增字符串扩张方法includes()、startsWith()、endsWith()1.find()该方法主要应用于查找第一个符合条件的数组元素,即…

    2022年6月13日
    80
  • Xmind快捷键大全(总结)[通俗易懂]

    Xmind快捷键大全(总结)[通俗易懂]在Xmind中,快捷键是可以大大提高绘图效率的存在。掌握常用的快捷键组合,就可以在键盘上运指如飞,快速地进行思维导图的绘制。主要的快捷键类型有四种,分别是:文件(File)、插入(Insert)、编辑(Edit)和查看(View)。文件文件快捷键,指的是对当前文件整体的一个操作,常见的功能有保存、关闭、打开和新建等。插入XMind:支持添加丰富的主题元素,你可以添加标记、标签、超链接、附件、主题链接、笔记等丰富的主题元素来表达复杂的逻辑层次和丰富的想法。编辑【编辑】类型快捷

    2022年6月6日
    68
  • linux的ftp命令大全_linux tar命令详解

    linux的ftp命令大全_linux tar命令详解ftp主机名/IP会提示输入用户名和密码匿名登录:用户名输入:anonymous密码输入:一个邮箱格式的任意字符串ascii#设定以ASCII方式传送文件(缺省值)bell#每完成一次文件传送,报警提示.binary#设定以二进制方式传送文件.bye#终止主机FTP进程,并退出FTP管理方式.case#当为ON时,用MGET命令拷贝的文件名到本地…

    2026年2月8日
    4
  • 为你的爬虫添加 IP 池反反爬策略[通俗易懂]

    为你的爬虫添加 IP 池反反爬策略[通俗易懂]为你的爬虫添加 IP 池反反爬策略

    2022年4月21日
    66
  • csgo开箱网站都有哪些_csgo官方承认的开箱网站

    csgo开箱网站都有哪些_csgo官方承认的开箱网站csgo开箱网站有哪些?csgo开箱网站大全以下国内知名CSGO开箱网站网站状态优惠码/推广码官网直达链接直接取回csgogoincsgo直接取回csgogoskinsdog直接取回csgo88hash直接取回csgogoskskins直接取回csgofateskins可取回暂无yskins直接取回csgocoolkaixiang可取回csgogopiggycase以下国外知名CSGO开箱网站

    2022年10月6日
    4
  • [日常] Go语言圣经-匿名函数习题

    [日常] Go语言圣经-匿名函数习题

    2021年5月26日
    98

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号