• activiti02


    二级审批流程的实现

    1.设计一个二级审批流程

    2.创建三个不同用户组为流程参与者

    3.参与者协同完成流程

    second_approve.bpmn 设计

    对应xml文件如下

      1 <?xml version="1.0" encoding="UTF-8"?>
      2 <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:activiti="http://activiti.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.activiti.org/test">
      3   <process id="LeaveProcess" name="请假流程" isExecutable="true">
      4     <startEvent id="startevent" name="开始"></startEvent>
      5     <userTask id="submitform" name="填写请假申请">
      6       <extensionElements>
      7         <activiti:formProperty id="message" name="申请信息" type="string" required="true"></activiti:formProperty>
      8         <activiti:formProperty id="name" name="申请人姓名" type="string" required="true"></activiti:formProperty>
      9         <activiti:formProperty id="submitTime" name="提交时间" type="date" datePattern="yyyy-MM-dd" required="true"></activiti:formProperty>
     10         <activiti:formProperty id="submitType" name="确认申请" type="string" required="true"></activiti:formProperty>
     11       </extensionElements>
     12     </userTask>
     13     <sequenceFlow id="flow1" sourceRef="startevent" targetRef="submitform"></sequenceFlow>
     14     <exclusiveGateway id="decideSubmit" name="提交或取消"></exclusiveGateway>
     15     <sequenceFlow id="flow2" sourceRef="submitform" targetRef="decideSubmit"></sequenceFlow>
     16     <userTask id="ZG_approve" name="部门主管审批">
     17       <extensionElements>
     18         <activiti:formProperty id="ZGapprove" name="主管审批结果" type="string" required="true"></activiti:formProperty>
     19         <activiti:formProperty id="ZGmessage" name="主管备注" type="string" required="true"></activiti:formProperty>
     20       </extensionElements>
     21     </userTask>
     22     <sequenceFlow id="flow3" sourceRef="decideSubmit" targetRef="ZG_approve">
     23       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${submitType=="y" || submitType=="Y"}]]></conditionExpression>
     24     </sequenceFlow>
     25     <exclusiveGateway id="decideZGapprove" name="主管审批校验"></exclusiveGateway>
     26     <sequenceFlow id="flow4" sourceRef="ZG_approve" targetRef="decideZGapprove"></sequenceFlow>
     27     <userTask id="ZJL_approve" name="总经理审批">
     28       <extensionElements>
     29         <activiti:formProperty id="ZJLapprove" name="总经理审批结果" type="string" required="true"></activiti:formProperty>
     30         <activiti:formProperty id="ZJLmessage" name="总经理备注" type="string" required="true"></activiti:formProperty>
     31       </extensionElements>
     32     </userTask>
     33     <sequenceFlow id="flow5" sourceRef="decideZGapprove" targetRef="ZJL_approve">
     34       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${ZGapprove=="y" || ZGapprove=="Y"}]]></conditionExpression>
     35     </sequenceFlow>
     36     <exclusiveGateway id="decideZJLapprove" name="总经理审批校验"></exclusiveGateway>
     37     <sequenceFlow id="flow6" sourceRef="ZJL_approve" targetRef="decideZJLapprove"></sequenceFlow>
     38     <endEvent id="endevent" name="结束"></endEvent>
     39     <sequenceFlow id="flow7" sourceRef="decideZJLapprove" targetRef="endevent">
     40       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${ZJLapprove=="y" || ZJLapprove=="Y"}]]></conditionExpression>
     41     </sequenceFlow>
     42     <endEvent id="endeventCancel" name="取消"></endEvent>
     43     <sequenceFlow id="flow8" sourceRef="decideSubmit" targetRef="endeventCancel">
     44       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${submitType=="n" || submitType=="N"}]]></conditionExpression>
     45     </sequenceFlow>
     46     <sequenceFlow id="flow9" sourceRef="decideZGapprove" targetRef="submitform">
     47       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${ZGapprove=="n" || ZGapprove=="N"}]]></conditionExpression>
     48     </sequenceFlow>
     49     <sequenceFlow id="flow10" sourceRef="decideZJLapprove" targetRef="submitform">
     50       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${ZJLapprove=="n" || ZJLapprove=="N"}]]></conditionExpression>
     51     </sequenceFlow>
     52   </process>
     53   <bpmndi:BPMNDiagram id="BPMNDiagram_LeaveProcess">
     54     <bpmndi:BPMNPlane bpmnElement="LeaveProcess" id="BPMNPlane_LeaveProcess">
     55       <bpmndi:BPMNShape bpmnElement="startevent" id="BPMNShape_startevent">
     56         <omgdc:Bounds height="35.0" width="35.0" x="65.0" y="279.0"></omgdc:Bounds>
     57       </bpmndi:BPMNShape>
     58       <bpmndi:BPMNShape bpmnElement="submitform" id="BPMNShape_submitform">
     59         <omgdc:Bounds height="55.0" width="105.0" x="145.0" y="269.0"></omgdc:Bounds>
     60       </bpmndi:BPMNShape>
     61       <bpmndi:BPMNShape bpmnElement="decideSubmit" id="BPMNShape_decideSubmit">
     62         <omgdc:Bounds height="40.0" width="40.0" x="295.0" y="277.0"></omgdc:Bounds>
     63       </bpmndi:BPMNShape>
     64       <bpmndi:BPMNShape bpmnElement="ZG_approve" id="BPMNShape_ZG_approve">
     65         <omgdc:Bounds height="55.0" width="105.0" x="380.0" y="270.0"></omgdc:Bounds>
     66       </bpmndi:BPMNShape>
     67       <bpmndi:BPMNShape bpmnElement="decideZGapprove" id="BPMNShape_decideZGapprove">
     68         <omgdc:Bounds height="40.0" width="40.0" x="530.0" y="278.0"></omgdc:Bounds>
     69       </bpmndi:BPMNShape>
     70       <bpmndi:BPMNShape bpmnElement="ZJL_approve" id="BPMNShape_ZJL_approve">
     71         <omgdc:Bounds height="55.0" width="105.0" x="615.0" y="271.0"></omgdc:Bounds>
     72       </bpmndi:BPMNShape>
     73       <bpmndi:BPMNShape bpmnElement="decideZJLapprove" id="BPMNShape_decideZJLapprove">
     74         <omgdc:Bounds height="40.0" width="40.0" x="765.0" y="279.0"></omgdc:Bounds>
     75       </bpmndi:BPMNShape>
     76       <bpmndi:BPMNShape bpmnElement="endevent" id="BPMNShape_endevent">
     77         <omgdc:Bounds height="35.0" width="35.0" x="850.0" y="282.0"></omgdc:Bounds>
     78       </bpmndi:BPMNShape>
     79       <bpmndi:BPMNShape bpmnElement="endeventCancel" id="BPMNShape_endeventCancel">
     80         <omgdc:Bounds height="35.0" width="35.0" x="395.0" y="329.0"></omgdc:Bounds>
     81       </bpmndi:BPMNShape>
     82       <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
     83         <omgdi:waypoint x="100.0" y="296.0"></omgdi:waypoint>
     84         <omgdi:waypoint x="145.0" y="296.0"></omgdi:waypoint>
     85       </bpmndi:BPMNEdge>
     86       <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
     87         <omgdi:waypoint x="250.0" y="296.0"></omgdi:waypoint>
     88         <omgdi:waypoint x="295.0" y="297.0"></omgdi:waypoint>
     89       </bpmndi:BPMNEdge>
     90       <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
     91         <omgdi:waypoint x="335.0" y="297.0"></omgdi:waypoint>
     92         <omgdi:waypoint x="380.0" y="297.0"></omgdi:waypoint>
     93       </bpmndi:BPMNEdge>
     94       <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
     95         <omgdi:waypoint x="485.0" y="297.0"></omgdi:waypoint>
     96         <omgdi:waypoint x="530.0" y="298.0"></omgdi:waypoint>
     97       </bpmndi:BPMNEdge>
     98       <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
     99         <omgdi:waypoint x="570.0" y="298.0"></omgdi:waypoint>
    100         <omgdi:waypoint x="615.0" y="298.0"></omgdi:waypoint>
    101       </bpmndi:BPMNEdge>
    102       <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
    103         <omgdi:waypoint x="720.0" y="298.0"></omgdi:waypoint>
    104         <omgdi:waypoint x="765.0" y="299.0"></omgdi:waypoint>
    105       </bpmndi:BPMNEdge>
    106       <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
    107         <omgdi:waypoint x="805.0" y="299.0"></omgdi:waypoint>
    108         <omgdi:waypoint x="850.0" y="299.0"></omgdi:waypoint>
    109       </bpmndi:BPMNEdge>
    110       <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
    111         <omgdi:waypoint x="315.0" y="317.0"></omgdi:waypoint>
    112         <omgdi:waypoint x="315.0" y="346.0"></omgdi:waypoint>
    113         <omgdi:waypoint x="395.0" y="346.0"></omgdi:waypoint>
    114       </bpmndi:BPMNEdge>
    115       <bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
    116         <omgdi:waypoint x="550.0" y="318.0"></omgdi:waypoint>
    117         <omgdi:waypoint x="549.0" y="382.0"></omgdi:waypoint>
    118         <omgdi:waypoint x="397.0" y="382.0"></omgdi:waypoint>
    119         <omgdi:waypoint x="197.0" y="382.0"></omgdi:waypoint>
    120         <omgdi:waypoint x="197.0" y="324.0"></omgdi:waypoint>
    121       </bpmndi:BPMNEdge>
    122       <bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10">
    123         <omgdi:waypoint x="785.0" y="279.0"></omgdi:waypoint>
    124         <omgdi:waypoint x="784.0" y="222.0"></omgdi:waypoint>
    125         <omgdi:waypoint x="505.0" y="222.0"></omgdi:waypoint>
    126         <omgdi:waypoint x="197.0" y="222.0"></omgdi:waypoint>
    127         <omgdi:waypoint x="197.0" y="269.0"></omgdi:waypoint>
    128       </bpmndi:BPMNEdge>
    129     </bpmndi:BPMNPlane>
    130   </bpmndi:BPMNDiagram>
    131 </definitions>

    新建springboot工程

    引入依赖

     <dependencies>
    
            <dependency>
                <groupId>org.activiti</groupId>
                <artifactId>activiti-engine</artifactId>
                <version>6.0.0</version>
            </dependency>
    
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
     
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.1.11</version>
            </dependency>
     
            <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.3.176</version>
            </dependency>
        </dependencies>

    简化logback输出,logback.xml

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <configuration>
     3     <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
     4     <property name="LOG_HOME" value="/home/tomcatlog/logs/agent" />
     5     <property name="plain" value="%msg%n" />
     6 
     7     <!-- 控制台输出 -->
     8     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     9         <encoder>
    10             <pattern>${plain}</pattern>
    11         </encoder>
    12     </appender>
    13 
    14     <!-- 按照每天生成日志文件 -->
    15     <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    16         <file>${LOG_HOME}/agent.log</file>
    17         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    18             <!--日志文件输出的文件名 -->
    19             <fileNamePattern>${LOG_HOME}/agent.%d{yyyy-MM-dd}.log
    20             </fileNamePattern>
    21             <!--日志文件保留天数 -->
    22             <maxHistory>30</maxHistory>
    23         </rollingPolicy>
    24         <encoder>
    25             <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
    26             <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{80} - %msg%n
    27             </pattern>
    28         </encoder>
    29     </appender>
    30 
    31     <logger name="jdbc.sqlonly" level="OFF" />
    32     <logger name="jdbc.resultsettable" level="OFF" />
    33     <logger name="jdbc.sqltiming" level="erroe" />
    34     <logger name="jdbc.audit" level="error" />
    35     <logger name="jdbc.connection" level="error" />
    36     <logger name="jdbc.resultset" level="error" />
    37     <logger name="root">
    38         <level value="ERROR"/>
    39     </logger>
    40     <logger name="com.imooc">
    41         <level value="DEBUG"/>
    42     </logger>
    43 
    44     <!-- 日志输出级别 -->
    45     <root level="info"><!-- ERROR、WARN、INFO、DEBUG -->
    46         <appender-ref ref="STDOUT" />
    47         <appender-ref ref="FILE" />
    48     </root>
    49 </configuration>

    resources引入second_approve.bpmn20.xml文件

    新建启动类Main.class

    创建流程引擎

    部署流程定义文件

    启动运行流程

    处理流程任务

    按照以上四步构建引动类,为了简化启动类,建议对每个方法进行重构,CTRL+ALT+M快捷键

      1 package com.imooc.activiti.helloword;
      2 
      3 
      4 import com.google.common.collect.Maps;
      5 import org.activiti.engine.*;
      6 import org.activiti.engine.form.FormProperty;
      7 import org.activiti.engine.form.TaskFormData;
      8 import org.activiti.engine.impl.form.DateFormType;
      9 import org.activiti.engine.impl.form.StringFormType;
     10 import org.activiti.engine.repository.Deployment;
     11 import org.activiti.engine.repository.DeploymentBuilder;
     12 import org.activiti.engine.repository.ProcessDefinition;
     13 import org.activiti.engine.runtime.ProcessInstance;
     14 import org.activiti.engine.task.Task;
     15 import org.slf4j.Logger;
     16 import org.slf4j.LoggerFactory;
     17 
     18 import java.text.ParseException;
     19 import java.text.SimpleDateFormat;
     20 import java.util.Date;
     21 import java.util.List;
     22 import java.util.Map;
     23 import java.util.Scanner;
     24 
     25 public class Main {
     26 
     27     private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
     28 
     29     public static void main(String[] args) throws ParseException {
     30         LOGGER.info("启动程序");
     31         //创建流程引擎
     32         ProcessEngine processEngine = getProcessEngine();
     33 
     34         //部署流程定义文件
     35         ProcessDefinition processDefinition = getProcessDefinition(processEngine);
     36 
     37         //启动运行流程
     38         ProcessInstance processInstance =getProcessInstance(processEngine, processDefinition);
     39 
     40         //处理流程任务
     41         Scanner scanner = new Scanner(System.in);
     42         while (processInstance != null && !processInstance.isEnded()) {   //判断流程不为空,且流程没有结束
     43             TaskService taskService = processEngine.getTaskService();
     44             List<Task> list = taskService.createTaskQuery().list();    //列出当前需要处理的任务
     45             LOGGER.info("待处理任务数量 [{}]", list.size());
     46             for (Task task : list) {
     47 
     48                 LOGGER.info("待处理任务 [{}]", task.getName());
     49                 Map<String, Object> variables = getStringObjectMap(processEngine, scanner, task);
     50                 taskService.complete(task.getId(),variables);
     51                 processInstance = processEngine.getRuntimeService().createProcessInstanceQuery()
     52                         .processInstanceId(processInstance.getId()).singleResult();
     53             }
     54         }
     55         scanner.close();
     56         LOGGER.info("结束程序");
     57 
     58     }
     59     //获取变量
     60     private static Map<String, Object> getStringObjectMap(ProcessEngine processEngine, Scanner scanner, Task task) throws ParseException {
     61         FormService formService = processEngine.getFormService();    //通过formService来获取form表单输入
     62         TaskFormData taskFormData = formService.getTaskFormData (task.getId());
     63         List<FormProperty> formProperties = taskFormData.getFormProperties();    //获取taskFormData的表单内容
     64         Map<String,Object> variables = Maps.newHashMap();    //这个Map键值对来存对应表单用户输入的内容
     65         for (FormProperty property : formProperties){   //property为表单中的内容
     66             String line = null;    //这里获取输入的信息
     67             if(StringFormType.class.isInstance(property.getType())){   //如果是String类型的话
     68                 LOGGER.info("请输入 [{}] ?" , property.getName());    //输入form表单的某一项内容
     69                 line = scanner.nextLine();
     70                 variables.put(property.getId(),line);
     71             }else if(DateFormType.class.isInstance(property.getType())){   //如果是日期类型的话
     72                 LOGGER.info("请输入 [{}] ? 格式为(yyyy-MM-dd)" , property.getName());    //输入form表单的某一项内容
     73                 line = scanner.nextLine();
     74                 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");   //设置输入的日期格式
     75                 Date date = dateFormat.parse(line);
     76                 variables.put(property.getId(),date);
     77             }else{
     78                 LOGGER.info("类型不支持 [{}]",property.getType());
     79             }
     80             LOGGER.info("您输入的内容是 [{}] " , line);
     81         }
     82         return variables;
     83     }
     84 
     85     private static ProcessInstance getProcessInstance(ProcessEngine processEngine, ProcessDefinition processDefinition) {
     86         RuntimeService runtimeService = processEngine.getRuntimeService();
     87         ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
     88         LOGGER.info("启动流程{}",processInstance.getProcessDefinitionKey());
     89         return processInstance;
     90     }
     91 
     92     private static ProcessDefinition getProcessDefinition(ProcessEngine processEngine) {
     93         RepositoryService repositoryService = processEngine.getRepositoryService();
     94         DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
     95         deploymentBuilder.addClasspathResource("second_approve.bpmn20.xml");
     96         Deployment deploy = deploymentBuilder.deploy();
     97         String id = deploy.getId();
     98         ProcessDefinition processDefinition = repositoryService
     99                 .createProcessDefinitionQuery()
    100                 .deploymentId(id)
    101                 .singleResult();
    102         LOGGER.info("流程定义对象{},流程定义id {}",processDefinition.getName(),processDefinition.getId());
    103         return processDefinition;
    104     }
    105 
    106     private static ProcessEngine getProcessEngine() {
    107         ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
    108         ProcessEngine processEngine = cfg.buildProcessEngine();
    109         String name = processEngine.getName();
    110         String version = ProcessEngine.VERSION;
    111         LOGGER.info("流程引擎名称{},版本{}",name,version);
    112         return processEngine;
    113     }
    114 
    115 
    116 }

    使用springboot打包

    更新pom.xml

        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.0.RELEASE</version>
            <relativePath/>
        </parent>
    
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>   <!-- 基于plugin启动这个程序 -->
                </plugin>
            </plugins>
        </build>

    在<dependencies></dependencies>中添加spring-boot的依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

    进入这个项目目录,然后输入  mvn package  ,就可以将项目打包:mvn package

    target目录中,可以看到两个jar包:

    直接使用以下指令来执行我们编译好的二级审批流程文件

    java-jar xxxxxx.jar

    将二级审批流程创建archetype脚手架

    打开源码目录 Activiti-6.x oolingarchetypesactiviti-archetype-unittest

    安装脚手架 mvn clean install

    copy activiti-archetype-unittest2

    修改pom.xml中的 artifactId

    创建main/java与main/resources两个目录

    修改Main.java中的package,后面路径改为 ${package}; package ${package}

    修改 META-INF/maven/archetype-metadata.xml

     1  <?xml version="1.0" encoding="UTF-8"?>
     2   <archetype-descriptor name="activiti-archetype-unittest2">
     3     <fileSets>
     4       <fileSet filtered="true" packaged="true">   <!-- filtered是否过滤,packaged:是否经过包结构过滤 -->
     5         <directory>src/main/java</directory>
     6         <includes>
     7           <include>**/*.java</include>
     8        </includes>
     9       </fileSet>
    10      <fileSet filtered="false" packaged="false">
    11        <directory>src/main/resources</directory>   <!-- 资源目录下面的三个文件 -->
    12        <includes>
    13          <include>activiti.cfg.xml</include>
    14          <include>LeaveProcess.bpmn20.xml</include>
    15         <include>logback.xml</include>
    16       </includes>
    17    </fileSet>
    18    <fileSet filtered="true" packaged="true">
    19        <directory>src/test/java</directory>
    20       <includes>
    21         <include>**/*.java</include>
    22        </includes>
    23      </fileSet>
    24      <fileSet filtered="true" packaged="true">
    25        <directory>src/test/resources</directory>
    26        <includes>
    27         <include>second_approve.bpmn20.xml</include>
    28       </includes>
    29      </fileSet>
    30  
    31   </fileSets>
    32  </archetype-descriptor>

    进入activiti-archetype-unittest2的路径下,执行 mvn clean install

    在本地的maven仓库中已经创建好的脚手架

    Create from archetype后Add Archetype

    GroupId org.activiti

    ArtifactId activiti-archetype-unittest2

    Version 6.0.0

    即可继续创建工程

  • 相关阅读:
    git 强制覆盖本地
    给mysql添加账户并且赋予权限
    laravel 地址栏传参不了问题
    订单系统开发02
    熵——信息增益
    熵——导读
    熵——自信息
    tensorflow在文本处理中的使用——skip-gram & CBOW原理总结
    霍夫曼树
    tensorflow在文本处理中的使用——Word2Vec预测
  • 原文地址:https://www.cnblogs.com/quyangyang/p/11136544.html
Copyright © 2020-2023  润新知