• springboot+flowable请假详细流程


    1. flowable-ui

    目前flowable-ui主要用于画流程图,流程图画完之后,再对XML做适当的修改

    docker安装使用flowable

    docker run -d -p 8080:8080 flowable/all-in-one
    

    进入flowable-ui界面

    http://127.0.0.1:8080/flowable-modeler

    2. springboot 使用

    2.1 准备流程文件

    Holiday_Request.bpmn20.xml,将文件放在resource/processes目录下,启动是会自动找流程文件部署

    <?xml version="1.0" encoding="UTF-8"?>
    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
      <process id="holiday-request" name="Holiday Request" isExecutable="true">
        <startEvent id="startEvent" flowable:formFieldValidation="true"></startEvent>
        <sequenceFlow id="sequenceFlow-df79157f-2c4c-467c-8f27-50e3e1c65795" sourceRef="startEvent" targetRef="approveTask"></sequenceFlow>
        <userTask id="approveTask" name="Approve or reject request" flowable:candidateGroups="dept-managers" flowable:formFieldValidation="true"></userTask>
        <sequenceFlow id="sequenceFlow-e262d0a2-be78-462e-a382-58a507462e77" sourceRef="approveTask" targetRef="decision"></sequenceFlow>
        <exclusiveGateway id="decision"></exclusiveGateway>
        <sequenceFlow id="sequenceFlow-4395dd85-dfe3-41e1-9160-5f47ac0755a7" sourceRef="decision" targetRef="externalSystemCall">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${approved}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="sequenceFlow-17d5b350-554f-40ad-a475-b38196d562d7" sourceRef="decision" targetRef="sendRejectionMail">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${!approved}]]></conditionExpression>
        </sequenceFlow>
        <serviceTask id="externalSystemCall" name="Enter holidays in external system" flowable:class="com.hsm.flow.callback.HolidayCallback"></serviceTask>
        <sequenceFlow id="sequenceFlow-a0666bbf-eccf-4c2f-8567-6131445fa9b6" sourceRef="externalSystemCall" targetRef="holidayApprovedTask"></sequenceFlow>
        <userTask id="holidayApprovedTask" name="Holiday approved" flowable:assignee="managers" flowable:formFieldValidation="true">
          <extensionElements>
            <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
          </extensionElements>
        </userTask>
        <sequenceFlow id="sequenceFlow-e7697e72-a60f-4b97-9cde-7af165951805" sourceRef="holidayApprovedTask" targetRef="approveEnd"></sequenceFlow>
        <serviceTask id="sendRejectionMail" name="Send out rejection email" flowable:class="com.hsm.flow.callback.SendRejectionMailCallback"></serviceTask>
        <sequenceFlow id="sequenceFlow-fbd52a13-630e-452b-9136-5939252f8c9f" sourceRef="sendRejectionMail" targetRef="rejectEnd"></sequenceFlow>
        <endEvent id="approveEnd"></endEvent>
        <endEvent id="rejectEnd"></endEvent>
      </process>
      <bpmndi:BPMNDiagram id="BPMNDiagram_holidayRequest">
        <bpmndi:BPMNPlane bpmnElement="holiday-request" id="BPMNPlane_holidayRequest">
          <bpmndi:BPMNShape bpmnElement="startEvent" id="BPMNShape_startEvent">
            <omgdc:Bounds height="30.0" width="30.0" x="240.0" y="255.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="approveTask" id="BPMNShape_approveTask">
            <omgdc:Bounds height="60.0" width="100.0" x="320.0" y="240.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="decision" id="BPMNShape_decision">
            <omgdc:Bounds height="40.0" width="40.0" x="470.0" y="250.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="externalSystemCall" id="BPMNShape_externalSystemCall">
            <omgdc:Bounds height="60.0" width="100.0" x="560.0" y="160.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="holidayApprovedTask" id="BPMNShape_holidayApprovedTask">
            <omgdc:Bounds height="60.0" width="100.0" x="710.0" y="160.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="sendRejectionMail" id="BPMNShape_sendRejectionMail">
            <omgdc:Bounds height="60.0" width="100.0" x="560.0" y="320.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="approveEnd" id="BPMNShape_approveEnd">
            <omgdc:Bounds height="28.0" width="28.0" x="860.0" y="176.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="rejectEnd" id="BPMNShape_rejectEnd">
            <omgdc:Bounds height="28.0" width="28.0" x="745.0" y="335.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNEdge bpmnElement="sequenceFlow-e7697e72-a60f-4b97-9cde-7af165951805" id="BPMNEdge_sequenceFlow-e7697e72-a60f-4b97-9cde-7af165951805">
            <omgdi:waypoint x="809.9499999999999" y="190.0"></omgdi:waypoint>
            <omgdi:waypoint x="860.0" y="190.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="sequenceFlow-fbd52a13-630e-452b-9136-5939252f8c9f" id="BPMNEdge_sequenceFlow-fbd52a13-630e-452b-9136-5939252f8c9f">
            <omgdi:waypoint x="659.949999999997" y="349.66442953020135"></omgdi:waypoint>
            <omgdi:waypoint x="745.0003059524752" y="349.09362216470777"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="sequenceFlow-e262d0a2-be78-462e-a382-58a507462e77" id="BPMNEdge_sequenceFlow-e262d0a2-be78-462e-a382-58a507462e77">
            <omgdi:waypoint x="419.9499999999756" y="270.0"></omgdi:waypoint>
            <omgdi:waypoint x="470.0" y="270.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="sequenceFlow-4395dd85-dfe3-41e1-9160-5f47ac0755a7" id="BPMNEdge_sequenceFlow-4395dd85-dfe3-41e1-9160-5f47ac0755a7">
            <omgdi:waypoint x="509.9189252336448" y="270.0"></omgdi:waypoint>
            <omgdi:waypoint x="522.0" y="270.0"></omgdi:waypoint>
            <omgdi:waypoint x="522.0" y="190.0"></omgdi:waypoint>
            <omgdi:waypoint x="560.0" y="190.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="sequenceFlow-17d5b350-554f-40ad-a475-b38196d562d7" id="BPMNEdge_sequenceFlow-17d5b350-554f-40ad-a475-b38196d562d7">
            <omgdi:waypoint x="509.9189252336448" y="270.0"></omgdi:waypoint>
            <omgdi:waypoint x="522.0" y="270.0"></omgdi:waypoint>
            <omgdi:waypoint x="522.0" y="350.0"></omgdi:waypoint>
            <omgdi:waypoint x="559.9999999999769" y="350.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="sequenceFlow-df79157f-2c4c-467c-8f27-50e3e1c65795" id="BPMNEdge_sequenceFlow-df79157f-2c4c-467c-8f27-50e3e1c65795">
            <omgdi:waypoint x="269.9499986183554" y="270.0"></omgdi:waypoint>
            <omgdi:waypoint x="319.9999999999394" y="270.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="sequenceFlow-a0666bbf-eccf-4c2f-8567-6131445fa9b6" id="BPMNEdge_sequenceFlow-a0666bbf-eccf-4c2f-8567-6131445fa9b6">
            <omgdi:waypoint x="659.9499999999999" y="190.0"></omgdi:waypoint>
            <omgdi:waypoint x="710.0" y="190.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
        </bpmndi:BPMNPlane>
      </bpmndi:BPMNDiagram>
    </definitions>
    

    2.2 准备pom文件

    <dependencies>
        <!-- knife4j,swagger增强版 -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>2.0.7</version>
        </dependency>
        <!-- 工作流 -->
        <!-- Flowable spring-boot 版套餐 -->
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-spring-boot-starter</artifactId>
            <version>6.6.0</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
            <scope>runtime</scope>
        </dependency>
     </dependencies>
    

    2.3 配置数据源

    server:
      port: 9099
    spring:
      application:
        name: spring-flowable
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://ip:3306/flowable?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false
        username: root
        password: 123456
    

    2.4 配置流程引擎文件

    ProcessEngineConfig.java

    @Configuration
    @Slf4j
    public class ProcessEngineConfig {
        /**
         * 初始化流程引擎
         * @return
         */
        @Primary
        @Bean(name = "processEngine")
        public ProcessEngine initProcessEngine(DataSource dataSource) {
            log.info("=============================ProcessEngineBegin=============================");
    
            // 流程引擎配置
            ProcessEngineConfiguration cfg = null;
    
            try {
                cfg = new StandaloneProcessEngineConfiguration()
                        .setDataSource(dataSource)
                        // 初始化基础表,不需要的可以改为 DB_SCHEMA_UPDATE_FALSE
                        .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 初始化流程引擎对象
            ProcessEngine processEngine = cfg.buildProcessEngine();
            log.info("=============================ProcessEngineEnd=============================");
            return processEngine;
        }
    }
    

    2.5 开始写代码

    实体类TaskResp.java

    @Data
    public class TaskResp {
        private String taskId;
        private String taskName;
    }
    

    控制器 HolidayController.java

    @RestController
    @Api(tags = "请求流程控制器", value = "请求流程控制器")
    @RequestMapping("/holiday")
    @Slf4j
    public class HolidayController {
        @Autowired
        private IHolidayService holidayService;
    
        @PostMapping("create")
        @ApiOperation(value = "创建请假申请", notes = "创建请假申请")
        public boolean createRequest(@RequestParam("userName") String userName,
                                     @RequestParam("reason") String reason,
                                     @RequestParam("days") Integer days){
            return holidayService.createRequest(userName,reason,days);
        }
    
        @GetMapping("list/task")
        @ApiOperation(value = "任务列表查询", notes = "任务列表查询")
        public List<TaskResp> listTask(@RequestParam(value = "userGroup",required = false) String userGroup,
                                       @RequestParam(value = "username",required = false) String username,
                                       @RequestParam(value = "taskName",required = false) String taskName,
                                       @RequestParam(value = "businessKey",required = false) String businessKey){
            return holidayService.listTask(userGroup,username,taskName,businessKey);
        }
    
        @GetMapping("complete/task")
        @ApiOperation(value = "审核任务", notes = "审核任务")
        public boolean completeTask(@RequestParam(value = "taskId",required = true) String taskId,
                                       @RequestParam(value = "approved",required = true) boolean approved){
            return holidayService.completeTask(taskId,approved);
        }
    }
    

    实现类HolidayService.java

    @Service
    public class HolidayService implements IHolidayService {
        @Autowired
        private RepositoryService repositoryService;
        @Autowired
        private RuntimeService runtimeService;
        @Autowired
        private TaskService taskService;
    
    
        private static final String processDefinitionId = "holiday-request";
    
        @Override
        public boolean createRequest(String userName, String reason, Integer days) {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(processDefinitionId)
                    .singleResult();
            Map<String, Object> variables = new HashMap<String, Object>();
            variables.put("userName", userName);
            variables.put("reason", reason);
            variables.put("days", days);
            ProcessInstance processInstance =
                    runtimeService.startProcessInstanceByKey(processDefinitionId, variables);
            return true;
        }
    
        @Override
        public List<TaskResp> listTask(String userGroup, String username, String taskName, String businessKey) {
            List<TaskResp> dataList = new ArrayList<>();
            TaskQuery taskQuery = taskService.createTaskQuery();
            if(StringUtils.isNotEmpty(username)){
                taskQuery.taskAssignee(username);
            }
            if(StringUtils.isNotEmpty(userGroup)){
                taskQuery.taskCandidateGroup(userGroup);
            }
            List<Task> list = taskQuery.list();
            for (Task task : list) {
                TaskResp taskResp = new TaskResp();
                taskResp.setTaskId(task.getId());
                taskResp.setTaskName(task.getName());
                dataList.add(taskResp);
            }
            return dataList;
        }
    
        @Override
        public boolean completeTask(String taskId, boolean approved) {
            Map<String, Object> variables = new HashMap<>();
            variables.put("approved",approved);
            variables.put("var",123);
            taskService.complete(taskId,variables);
            return true;
        }
    }
    

    回调类

    public class HolidayCallback  implements JavaDelegate {
        @Override
        public void execute(DelegateExecution execution) {
            System.out.println("审核通过了,保存假期数据入库");
        }
    }
    
    public class SendRejectionMailCallback implements JavaDelegate {
        @Override
        public void execute(DelegateExecution execution) {
            System.out.println("拒绝了申请,给申请人发送邮件");
        }
    }
    

    3. 流程说明

    看图说话,这里需要仔细看xml文件和流程扭转了

    github地址

    https://github.com/Steven-hsm/java-interview

    用户手册地址

    https://tkjohn.github.io/flowable-userguide/#_getting_started

  • 相关阅读:
    SQL语句执行效率及分析(note)
    双重检查锁定及单例模式
    可定制生命周期的缓存
    php CI框架高级视图功能,视图继承,多重继承,视图片段
    php 使用pdo连接postgresql
    python 学习整理
    phpmailer 发送邮件
    php syslog记录系统日志
    php 学习整理
    php 生成唯一id方法
  • 原文地址:https://www.cnblogs.com/steven158/p/15157527.html
Copyright © 2020-2023  润新知