zoukankan      html  css  js  c++  java
  • 基于flowable6.5的第一个demo

      因工作需要,本人现在在学习Flowable工作流。此处将自己学习和测试通过的demo展示给大家,希望对同为初学者的你有所帮助。

      对于什么是工作流,flowable和activiti的区别,各位可自行百度,此处不再赘述。

      直接上demo:

      1、环境搭建:jdk1.8+maven+eclipse

     创建标准的maven项目,项目框架截图如下:

     

      2、添加相关依赖:pom.xml

    <!-- https://mvnrepository.com/artifact/org.flowable/flowable-engine -->
    <dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-engine</artifactId>
    <version>6.5.0</version>
    </dependency>

    <dependency>
    <artifactId>junit</artifactId>
    <groupId>junit</groupId>
    <version>4.12</version>
    <scope>test</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
    <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.1.10</version>
    <scope>compile</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
    <dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>23.0</version>
    </dependency>

    <!-- 使用h2数据库,方便测试-->
    <dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.197</version>
    </dependency>

    
    

      3、使用flowable插件创建mywork.bpmn文件(因篇幅问题,只贴关键代码),flowable插件安装请自行百度

      mywork.png如下:

      mywork.bpmn:

    <process id="mywork" name="二级审批流程" isExecutable="true">
        <startEvent id="startEvent" name="开始"></startEvent>
        <userTask id="userDev" name="申请审批流程">
          <extensionElements>
            <activiti:formProperty id="message" name="申请信息" type="string" required="true"></activiti:formProperty>
            <activiti:formProperty id="name" name="申请人" type="string" required="true"></activiti:formProperty>
            <activiti:formProperty id="submitTime" name="提交时间" type="date" datePattern="yyyy-MM-dd" required="true"></activiti:formProperty>
            <activiti:formProperty id="submitType" name="确认申请" type="string" required="true"></activiti:formProperty>
          </extensionElements>
        </userTask>
        <sequenceFlow id="flow1" sourceRef="startEvent" targetRef="userDev"></sequenceFlow>
        <exclusiveGateway id="Dev_exclusivegateway" name="确认提交"></exclusiveGateway>
        <sequenceFlow id="flow2" sourceRef="userDev" targetRef="Dev_exclusivegateway"></sequenceFlow>
        <userTask id="userTL" name="主管审批">
          <extensionElements>
            <activiti:formProperty id="TLApprove" name="主管审批结果" type="string" required="true"></activiti:formProperty>
            <activiti:formProperty id="TLMessage" name="主管备注" type="string" required="true"></activiti:formProperty>
          </extensionElements>
        </userTask>
        <sequenceFlow id="flow3" sourceRef="Dev_exclusivegateway" targetRef="userTL">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${submitType == "y" || submitType =="Y"}]]></conditionExpression>
        </sequenceFlow>
        <endEvent id="endEvent" name="结束"></endEvent>
        <exclusiveGateway id="TL_exclusivegateway" name="主管审批结果"></exclusiveGateway>
        <sequenceFlow id="flow8" sourceRef="userTL" targetRef="TL_exclusivegateway"></sequenceFlow>
        <userTask id="userHR" name="人事审批">
          <extensionElements>
            <activiti:formProperty id="HRApprove" name="人事审批结果" type="string" required="true"></activiti:formProperty>
            <activiti:formProperty id="HRMessage" name="人事审批备注" type="string" required="true"></activiti:formProperty>
          </extensionElements>
        </userTask>
        <sequenceFlow id="flow9" sourceRef="TL_exclusivegateway" targetRef="userHR">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${TLApprove == "y" || TLApprove =="Y"}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="flow11" sourceRef="TL_exclusivegateway" targetRef="userDev">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${TLApprove == "N" || TLApprove =="n"}]]></conditionExpression>
        </sequenceFlow>
        <exclusiveGateway id="HR_exclusivegateway" name="人事审批结果"></exclusiveGateway>
        <sequenceFlow id="flow12" sourceRef="userHR" targetRef="HR_exclusivegateway"></sequenceFlow>
        <endEvent id="endEvent1" name="取消"></endEvent>
        <sequenceFlow id="flow13" sourceRef="HR_exclusivegateway" targetRef="endEvent1">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${HRApprove == "y" || HRApprove =="Y"}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="flow14" sourceRef="HR_exclusivegateway" targetRef="userDev">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${HRApprove == "n" || HRApprove =="N"}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="flow15" sourceRef="Dev_exclusivegateway" targetRef="endEvent1">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${submitType == "n" || submitType =="N"}]]></conditionExpression>
        </sequenceFlow>
    </process>

      4、创建主运行类:DemoMain.java

    package com.lx.activiti.helloworld;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Scanner;
    
    
    import org.flowable.engine.FormService;
    import org.flowable.engine.ProcessEngine;
    import org.flowable.engine.ProcessEngineConfiguration;
    import org.flowable.engine.RepositoryService;
    import org.flowable.engine.RuntimeService;
    import org.flowable.engine.TaskService;
    import org.flowable.engine.form.FormProperty;
    import org.flowable.engine.form.TaskFormData;
    import org.flowable.engine.impl.form.DateFormType;
    import org.flowable.engine.impl.form.StringFormType;
    import org.flowable.engine.repository.Deployment;
    import org.flowable.engine.repository.ProcessDefinition;
    import org.flowable.engine.runtime.ProcessInstance;
    import org.flowable.task.api.Task;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.google.common.collect.Maps;
    
    /**
     * 启动类
     * @author 
     *
     */
    public class DemoMain {
        private static final Logger logger = LoggerFactory.getLogger(DemoMain.class);
        
        public static void main(String[] args) throws ParseException {
            logger.info("启动程序");
            //抽取各步骤作为方法调用
            //1. 创建流程引擎
            ProcessEngine processEngine = getProcessEngine();
            
            //2. 部署流程文件
            ProcessDefinition processDefinition = getDeployment(processEngine);
            
            //3. 启动运行流程
            ProcessInstance processInstance =getProcessInstance(processEngine, processDefinition);
            
            //4. 处理流程任务
            //控制台输入
            Scanner scanner = new Scanner(System.in);
            //判断,当流程实例不为空,且流程没有结束时
            while (processInstance!=null && !processInstance.isEnded()) {
                //获取任务服务组件
                TaskService taskService = processEngine.getTaskService();
                //创建任务查询,将结果放入list集合中
                List<Task> list = taskService.createTaskQuery().list();
                logger.info("待处理任务数量: [{}]",list.size());
                //遍历list集合
                for (Task task : list) {
                    logger.info("待处理任务: [{}]",task.getName());
                    //获取表单服务组件
                    FormService formService = processEngine.getFormService();
                    //获取表单内容的集合formProperties
                    TaskFormData taskFormData = formService.getTaskFormData(task.getId());
                    List<FormProperty> formProperties = taskFormData.getFormProperties();
                    
                    HashMap<String, Object> variables = Maps.newHashMap();
                    String line = null;
                    //遍历formProperties
                    for (FormProperty property : formProperties) {
                        //判断,如果表单中定义的是字符串类型变量,则按该格式输入
                        if (StringFormType.class.isInstance(property.getType())) {
                            logger.info("请输入 {} ?",property.getName());
                            line = scanner.nextLine();
                            variables.put(property.getId(), line);
                            
                        //判断,如果表单中定义的是日期类型变量,按日期格式输入
                        }else if(DateFormType.class.isInstance(property.getType())) {
                            logger.info("请输入 {} ? 格式 (yyyy-MM-dd)",property.getName());
                            line = scanner.nextLine();
                            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                            Date date = dateFormat.parse(line);
                            variables.put(property.getId(), date);
                        }else {
                            logger.info("类型暂不支持 {} ",property.getType());
                        }
                        logger.info("你输入的是[{}]",line);
                    }
                    taskService.complete(task.getId(),variables);
                    
                    processInstance = processEngine.getRuntimeService()
                                        .createProcessInstanceQuery()
                                        .processInstanceId(processInstance.getId())
                                        .singleResult();
                }
            }
            logger.info("结束程序");
        }
    
        /**
         * 3. 获取流程实例:ProcessInstance,启动运行流程
         * @param processEngine
         * @param processDefinition
         * @return ProcessInstance
         */
        public static ProcessInstance getProcessInstance(ProcessEngine processEngine, ProcessDefinition processDefinition) {
            //获取运行服务
            RuntimeService runtimeService = processEngine.getRuntimeService();
            //传入流程定义文件id,调用startProcessInstanceById(),获取流程实例
            ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
            //获取流程部定义文件的key值
            logger.info("启动流程[ {}]",processInstance.getProcessDefinitionKey());
            return processInstance;
        }
    
        /**
         * 2 .  获取流程定义文件:ProcessDefinition , 部署流程
         * @param processEngine
         * @return ProcessDefinition
         */
        public static ProcessDefinition getDeployment(ProcessEngine processEngine) {
            //通过引擎获取仓储服务
            RepositoryService repositoryService = processEngine.getRepositoryService();
            //通过仓储服务链式调用,部署流程
            Deployment deploy = repositoryService.createDeployment()//得到流程部署
                                    .addClasspathResource("diagrams/mywork.bpmn")//加载资源
                                    .deploy();//部署流程
            String deployId = deploy.getId();
            //获取流程定义文件:processDefinition
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()//创建流程定义文件查询
                                                    .deploymentId(deployId)//传入流程部署ID
                                                    .singleResult();//根据查询条件;到数据库中查询唯一的数据记录,如果没有,则为空,如果有多条,则抛出异常
            logger.info("流程定义文件: [ {}] ,流程id: [{}]",processDefinition.getName(),processDefinition.getId());
            return processDefinition;
        }
         
        /**
         *  1. 创建流程引擎
         *  @return ProcessEngine
         */
        public static ProcessEngine getProcessEngine() {
            //获取流程配置文件
            ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
            //通过流程文件创建引擎
            ProcessEngine processEngine = cfg.buildProcessEngine();
            
            String name = processEngine.getName();
            String version = processEngine.VERSION;
            logger.info("流程引擎名称{},版本 [{}]}", name, version);
            return processEngine;
        }
    }

      5、运行该类,截取部分测试结果如下图:

  • 相关阅读:
    [LeetCode] Permutation Sequence, Solution
    [LeetCode] Spiral Matrix II, Solution
    同学你好, google到你的帖子,想问下为什么你的解法不用考虑到2个数相同的情况?比如4,4,8...
    [LeetCode] Regular Expression Matching, Solution
    {4,4,8}倒还好,不过{4,8}就会有问题了。这里倒是一个bug。一个可用的办法就是用一个vis...
    [LeetCode] Merge Intervals, Solution
    请问这个解法的时间复杂度怎么分析?谢谢!
    未做题
    dude, visited[i 1] == 0 should be visited[i 1]...
    发布一个开源的c++网络事件库【转载Zark@cppthinker.com】
  • 原文地址:https://www.cnblogs.com/gaoyangsixue/p/13560226.html
Copyright © 2011-2022 走看看