• 5步带你掌握工作流Activiti框架的使用


    摘要:本文通过一个工作流Activiti框架的具体使用示例,具体详尽的介绍了工作流Activiti框架的使用方式。

    本文分享自华为云社区《一个使用示例,五个操作步骤!从此轻松掌握项目中工作流的开发》,作者:攻城狮Chova。

    本文通过一个工作流Activiti框架的具体使用示例,具体详尽的介绍了工作流Activiti框架的使用方式。包括创建流程,发布流程,启动一个流程实例,完成一个流程实例以及挂起和激活一个流程实例。通过对工作流Activiti的具体使用步骤的掌握,基本上就能够学会了工作流Activiti的工作流程和具体使用。

    创建流程

    • 要想操作Activiti引擎,需要通过org.activiti.engine.ProcessEngine实例暴露的服务.就可以操作一个org.activiti.engine.ProcessEngine
    • 创建一个请假申请的工作业务流程:

    发布流程

    • 任何与“静态”资源有关的数据(比如流程定义)都可以通过RepositoryService访问,从概念上讲,所有静态数据都是Activiti的资源内容
    • src/test/resources/org/activiti/test目录下创建一个新的xml文件 VacationRequest.bpmn20.xml:
    <?xml version="1.0" encoding="UTF-8" ?>
    <definitions id="definitions"
                 targetNamespace="http://activiti.org/bpmn20"
                 xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:activiti="http://activiti.org/bpmn">
    
      <process id="vacationRequest" name="Vacation request">
    
        <startEvent id="request" activiti:initiator="employeeName">
          <extensionElements>
            <activiti:formProperty id="numberOfDays" name="Number of days" type="long" value="1" required="true"/>
            <activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
            <activiti:formProperty id="vacationMotivation" name="Motivation" type="string" />
          </extensionElements>
        </startEvent>
        <sequenceFlow id="flow1" sourceRef="request" targetRef="handleRequest" />
    
        <userTask id="handleRequest" name="Handle vacation request" >
          <documentation>
            ${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${vacationMotivation}).
          </documentation>
          <extensionElements>
             <activiti:formProperty id="vacationApproved" name="Do you approve this vacation" type="enum" required="true">
              <activiti:value id="true" name="Approve" />
              <activiti:value id="false" name="Reject" />
            </activiti:formProperty>
            <activiti:formProperty id="managerMotivation" name="Motivation" type="string" />
          </extensionElements>
          <potentialOwner>
            <resourceAssignmentExpression>
              <formalExpression>management</formalExpression>
            </resourceAssignmentExpression>
          </potentialOwner>
        </userTask>
        <sequenceFlow id="flow2" sourceRef="handleRequest" targetRef="requestApprovedDecision" />
    
        <exclusiveGateway id="requestApprovedDecision" name="Request approved?" />
        <sequenceFlow id="flow3" sourceRef="requestApprovedDecision" targetRef="sendApprovalMail">
          <conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'true'}</conditionExpression>
        </sequenceFlow>
    
        <task id="sendApprovalMail" name="Send confirmation e-mail" />
        <sequenceFlow id="flow4" sourceRef="sendApprovalMail" targetRef="theEnd1" />
        <endEvent id="theEnd1" />
    
        <sequenceFlow id="flow5" sourceRef="requestApprovedDecision" targetRef="adjustVacationRequestTask">
          <conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'false'}</conditionExpression>
        </sequenceFlow>
    
        <userTask id="adjustVacationRequestTask" name="Adjust vacation request">
          <documentation>
            Your manager has disapproved your vacation request for ${numberOfDays} days.
            Reason: ${managerMotivation}
          </documentation>
          <extensionElements>
            <activiti:formProperty id="numberOfDays" name="Number of days" value="${numberOfDays}" type="long" required="true"/>
            <activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" value="${startDate}" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
            <activiti:formProperty id="vacationMotivation" name="Motivation" value="${vacationMotivation}" type="string" />
            <activiti:formProperty id="resendRequest" name="Resend vacation request to manager?" type="enum" required="true">
              <activiti:value id="true" name="Yes" />
              <activiti:value id="false" name="No" />
            </activiti:formProperty>
          </extensionElements>
          <humanPerformer>
            <resourceAssignmentExpression>
              <formalExpression>${employeeName}</formalExpression>
            </resourceAssignmentExpression>
          </humanPerformer>
        </userTask>
        <sequenceFlow id="flow6" sourceRef="adjustVacationRequestTask" targetRef="resendRequestDecision" />
    
        <exclusiveGateway id="resendRequestDecision" name="Resend request?" />
        <sequenceFlow id="flow7" sourceRef="resendRequestDecision" targetRef="handleRequest">
          <conditionExpression xsi:type="tFormalExpression">${resendRequest == 'true'}</conditionExpression>
        </sequenceFlow>
    
         <sequenceFlow id="flow8" sourceRef="resendRequestDecision" targetRef="theEnd2">
          <conditionExpression xsi:type="tFormalExpression">${resendRequest == 'false'}</conditionExpression>
        </sequenceFlow>
        <endEvent id="theEnd2" />
    
      </process>
    
    </definitions>
    • 为了让Activiti引擎知道这个流程,我们必须先进行[发布],发布意味着引擎会把BPMN 2.0 xml解析成可以执行的东西,发布包中的所有流程定义都会添加到数据库中.这样,当引擎重启时,它依然可以获得[已发布]的流程:
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    repositoryService.createDeployment()
      .addClasspathResource("org/activiti/test/VacationRequest.bpmn20.xml")
      .deploy();
    
    Log.info("Number of process definitions: " + repositoryService.createProcessDefinitionQuery().count());

    启动一个流程实例

    • 把流程定义发布到Activiti引擎后,可以基于它发起新流程实例.
    • 对每个流程定义,都可以有很多流程实例.流程定义是"蓝图",流程实例是它的一个运行的执行
    • 所有与流程运行状态相关的东西都可以通过RuntimeService获得.有很多方法可以启动一个新流程实例.
      • 可以在流程实例启动时添加一些流程变量, 因为第一个用户任务的表达式需要这些变量.流程变量经常会被用到,因为它们赋予来自同一个流程定义的不同流程实例的特别含义
      • 流程变量是区分流程实例的关键
      • 下面使用定义在流程定义xml 中的key来启动流程实例:
    Map<String, Object> variables = new HashMap<String, Object>();
    variables.put("employeeName", "Kermit");
    variables.put("numberOfDays", new Integer(4));
    variables.put("vacationMotivation", "I'm really tired!");
    
    RuntimeService runtimeService = processEngine.getRuntimeService();
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacationRequest", variables);
    
    // Verify that we started a new process instance
    Log.info("Number of process instances: " + runtimeService.createProcessInstanceQuery().count());

    完成任务

    • 流程启动后,第一步就是用户任务.这是必须由系统用户处理的一个环节.
    • 用户会有一个"任务列表",展示了所有必须由整个用户处理的任务.下面是对应的查询:
    • // Fetch all tasks for the management group
      TaskService taskService = processEngine.getTaskService();
      List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
      for (Task task : tasks) {
        Log.info("Task available: " + task.getName());
      }
      为了让流程实例继续运行,我们**需要完成整个任务.**对Activiti来说,就是需要complete任务:
    Task task = tasks.get(0);
    
    Map<String, Object> taskVariables = new HashMap<String, Object>();
    taskVariables.put("vacationApproved", "false");
    taskVariables.put("managerMotivation", "We have a tight deadline!");
    taskService.complete(task.getId(), taskVariables);
    • 然后流程实例就会进入到下一个环节
    • 下一环节允许员工通过表单调整原始的请假申请.员工可以重新提交请假申请,这会使流程重新进入到第一个任务

    挂起或激活一个流程

    • 可以挂起一个流程定义,当挂起流程定义时,就不能创建新流程了,会抛出一个异常.可以通过RepositoryService挂起一个流程:
    repositoryService.suspendProcessDefinitionByKey("vacationRequest");
    try {
      runtimeService.startProcessInstanceByKey("vacationRequest");
    } catch (ActivitiException e) {
      e.printStackTrace();
    }
    • 要想重新激活一个流程定义,可以调用repositoryService.activateProcessDefinitionXXX方法
    • 也可以挂起一个流程实例:
      • 挂起时,流程不能继续执行:比如,完成任务会抛出异常,异步操作(比如定时器)也不会执行.挂起流程实例可以调用runtimeService.suspendProcessInstance方法
      • 激活流程实例可以调用runtimeService.activateProcessInstanceXXX方法

     

    点击关注,第一时间了解华为云新鲜技术~

  • 相关阅读:
    java之jvm学习笔记五(实践写自己的类装载器)
    java之jvm学习笔记二(类装载器的体系结构)
    链式线性表
    java之jvm学习笔记十三(jvm基本结构)
    Java用户登陆界面
    李兴华JavaWeb开发笔记
    Java IO学习笔记:概念与原理
    Linux下一个简单的日志系统的设计及其C代码实现
    关于Core Location-ios定位
    C语言中main函数的參数具体解释
  • 原文地址:https://www.cnblogs.com/huaweiyun/p/15775014.html
Copyright © 2020-2023  润新知