<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一萬(wàn)字帶你入門(mén) Activiti 工作流,通俗易懂!

          共 43860字,需瀏覽 88分鐘

           ·

          2022-11-18 11:38


          來(lái)源:blog.csdn.net/Mr_97xu/article/details/112899079

          概念

          工作流。通過(guò)計(jì)算機(jī)對(duì)業(yè)務(wù)流程自動(dòng)化執(zhí)行管理,主要解決的是“使在多個(gè)參與者之間按照某種預(yù)定義的規(guī)則自動(dòng)進(jìn)行傳遞文檔、信息或任務(wù)的過(guò)程,從而實(shí)現(xiàn)某個(gè)預(yù)期的業(yè)務(wù)目標(biāo),或者促使此目標(biāo)的實(shí)現(xiàn)”。

          Activiti7

          介紹

          Activiti是一個(gè)工作流引擎,Activiti可以將業(yè)務(wù)系統(tǒng)中復(fù)雜的業(yè)務(wù)流程抽取出來(lái),使用專(zhuān)門(mén)的建模語(yǔ)言BPMN2.0進(jìn)行定義,業(yè)務(wù)流程按照預(yù)先定義的流程進(jìn)行執(zhí)行,實(shí)現(xiàn)了系統(tǒng)的流程由Activiti進(jìn)行管理,減少業(yè)務(wù)系統(tǒng)由于流程變更進(jìn)行系統(tǒng)升級(jí)改造的工作量,從而提高系統(tǒng)的健壯性,同時(shí)也減少了系統(tǒng)開(kāi)發(fā)維護(hù)成本。

          在使用activiti之前,首先需要編寫(xiě)activiti.cfg.xml配置文件。并且引入相關(guān)依賴(lài)。

          <dependencies>
              <!--activiti的核心包-->
              <dependency>
                  <groupId>org.activiti</groupId>
                  <artifactId>activiti-engine</artifactId>
                  <version>6.0.0</version>
              </dependency>
              <dependency>
                  <groupId>org.activiti</groupId>
                  <artifactId>activiti-spring</artifactId>
                  <version>6.0.0</version>
              </dependency>
              <dependency>
                  <groupId>org.activiti</groupId>
                  <artifactId>activiti-bpmn-model</artifactId>
                  <version>6.0.0</version>
              </dependency>
              <dependency>
                  <groupId>javax.servlet</groupId>
                  <artifactId>servlet-api</artifactId>
                  <version>2.5</version>
              </dependency>
              <dependency>
                  <groupId>org.activiti</groupId>
                  <artifactId>activiti-bpmn-converter</artifactId>
                  <version>6.0.0</version>
              </dependency>
              <dependency>
                  <groupId>org.activiti</groupId>
                  <artifactId>activiti-json-converter</artifactId>
                  <version>6.0.0</version>
              </dependency>
              <dependency>
                  <groupId>org.activiti</groupId>
                  <artifactId>activiti-bpmn-layout</artifactId>
                  <version>6.0.0</version>
              </dependency>
              <dependency>
                  <groupId>org.activiti.cloud</groupId>
                  <artifactId>activiti-cloud-services-api</artifactId>
                  <version>7-201710-EA</version>
              </dependency>
              <dependency>
                  <groupId>aspectj</groupId>
                  <artifactId>aspectjweaver</artifactId>
                  <version>1.5.4</version>
              </dependency>
              <dependency>
                  <groupId>mysql</groupId>
                  <artifactId>mysql-connector-java</artifactId>
                  <version>5.1.40</version>
              </dependency>
              <dependency>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-test</artifactId>
                  <version>5.0.7.RELEASE</version>
              </dependency>
              <dependency>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-core</artifactId>
                  <version>4.1.6.RELEASE</version>
              </dependency>
              <dependency>
                  <groupId>org.mybatis</groupId>
                  <artifactId>mybatis</artifactId>
                  <version>3.4.5</version>
              </dependency>
              <dependency>
                  <groupId>commons-dbcp</groupId>
                  <artifactId>commons-dbcp</artifactId>
                  <version>1.4</version>
              </dependency>
              <dependency>
                  <groupId>junit</groupId>
                  <artifactId>junit</artifactId>
                  <version>4.12</version>
              </dependency>
              <dependency>
                  <groupId>log4j</groupId>
                  <artifactId>log4j</artifactId>
                  <version>1.2.17</version>
              </dependency>
              <dependency>
                  <groupId>org.slf4j</groupId>
                  <artifactId>slf4j-log4j12</artifactId>
                  <version>1.7.21</version>
              </dependency>
              <dependency>
                  <groupId>org.slf4j</groupId>
                  <artifactId>slf4j-api</artifactId>
                  <version>1.7.25</version>
              </dependency>
              <dependency>
                  <groupId>commons-io</groupId>
                  <artifactId>commons-io</artifactId>
                  <version>2.6</version>
              </dependency>
              <dependency>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
                  <version>1.16.18</version>
                  <scope>provided</scope>
              </dependency>
          </dependencies>

          activiti.cfg.xml

          activiti的引擎配置文件,包括:ProcessEngineConfiguration的定義、數(shù)據(jù)源定義、事務(wù)管理器等。其實(shí)就是一個(gè)Spring配置文件。

          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans
                                      http://www.springframework.org/schema/beans/spring-beans.xsd"
          >

              <!--dbcp連接池-->
              <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
                  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                  <property name="url" value="jdbc:mysql://localhost:3306/activiti"/>
                  <property name="username" value="root"/>
                  <property name="password" value="root"/>
                  <property name="maxActive" value="3"/>
                  <property name="maxIdle" value="1"/>
              </bean>

              <!--在默認(rèn)方式下,bean的id固定為processEngineConfiguration-->
              <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
                  <!--配置數(shù)據(jù)庫(kù)相關(guān)信息-->
                  <property name="dataSource" ref="dataSource"/>
                  <!--
                      activiti數(shù)據(jù)庫(kù)表處理策略
                          false(默認(rèn)值):檢查數(shù)據(jù)庫(kù)的版本和依賴(lài)庫(kù)的版本,如果不匹配就拋出異常
                          true:構(gòu)建流程引擎時(shí),執(zhí)行檢查,如果需要就執(zhí)行更新。如果表不存在,就創(chuàng)建。
                          create-drop:構(gòu)建流程引擎時(shí)創(chuàng)建數(shù)據(jù)庫(kù)報(bào)表,關(guān)閉流程引擎時(shí)就刪除這些表。
                          drop-create:先刪除表再創(chuàng)建表。
                          create:構(gòu)建流程引擎時(shí)創(chuàng)建數(shù)據(jù)庫(kù)表,關(guān)閉流程引擎時(shí)不刪除這些表
                  -->
                  <property name="databaseSchemaUpdate" value="true"/>
                  <property name="asyncExecutorActivate" value="false"/>
                  <property name="mailServerHost" value="mail.my-corp.com"/>
                  <property name="mailServerPort" value="5025"/>
              </bean>

          </beans>

          Activiti流程框架,在前期主要需要了解的就是數(shù)據(jù)庫(kù)表的創(chuàng)建、流程的部署、流程的啟動(dòng)和各個(gè)階段任務(wù)的完成。

          流程引擎配置類(lèi)

          流程引擎配置類(lèi)(ProcessEngineConfiguration),通過(guò) ProcessEngineConfiguration 可以創(chuàng)建工作流引擎 ProceccEngine。

          工作流引擎的創(chuàng)建

          工作流引擎的創(chuàng)建主要有兩種方式:默認(rèn)創(chuàng)建方式和一般創(chuàng)建方式

          默認(rèn)創(chuàng)建方式

          ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
          System.out.println(processEngine);

          一般創(chuàng)建方式

          //使用自定義方式創(chuàng)建
          ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
          //獲取流程引擎對(duì)象:通過(guò) ProcessEngineConfiguration 創(chuàng)建 ProcessEngine,此時(shí)會(huì)創(chuàng)建數(shù)據(jù)庫(kù)
          ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();

          當(dāng)創(chuàng)建好工作流引擎后,對(duì)應(yīng)的數(shù)據(jù)庫(kù)中會(huì)自動(dòng)生成25張數(shù)據(jù)庫(kù)表。

              

          圖片

          ACT_GE_PROPERTY中會(huì)先展示下一次流程的ID(next.dbid),并且在下一次流程部署的時(shí)候,對(duì)下一次流程的ID進(jìn)行賦值。

          圖片

          Activiti表說(shuō)明

          這里以表名的前綴進(jìn)行說(shuō)明:

          圖片

          Service服務(wù)接口

          Activiti中還有許多的Service服務(wù)接口。這些Service 是工作流引擎提供用于進(jìn)行工作流部署、執(zhí)行、管理的服務(wù)接口,我們可以使用這些接口操作服務(wù)對(duì)應(yīng)的數(shù)據(jù)表。

          Service創(chuàng)建方式

          通過(guò)ProcessEngine創(chuàng)建Service方式:

          Runtimeservice runtimeService = processEngine.getRuntimeService();
          RepositoryService repositoryService = processEngine.getRepositoryService();
          TaskService taskService = processEngine.getTaskService();

          Service總覽

          圖片
          • RepositoryService

          Activiti 的資源管理類(lèi),提供了管理和控制流程發(fā)布包和流程定義的操作。使用工作流建模工具設(shè)計(jì)的業(yè)務(wù)流程圖需要使用此service將流程定義文件的內(nèi)容部署到計(jì)算機(jī)。除了部署流程定義以外,還可以查詢(xún)引擎中的發(fā)布包和流程定義。

          暫?;蚣せ畎l(fā)布包,對(duì)應(yīng)全部和特定流程定義。暫停意味著它們不能再執(zhí)行任何操作了,激活是對(duì)應(yīng)的反向操作。獲得多種資源,像是包含在發(fā)布包里的文件,或引擎自動(dòng)生成的流程圖。獲得流程定義的pojo版本,可以用來(lái)通過(guò)java解析流程,而不必通過(guò)xml。

          • Runtimeservice

          Activiti的流程運(yùn)行管理類(lèi)??梢詮倪@個(gè)服務(wù)類(lèi)中獲取很多關(guān)于流程執(zhí)行相關(guān)的信息

          • Taskservice

          Activiti的任務(wù)管理類(lèi)??梢詮倪@個(gè)類(lèi)中獲取任務(wù)的信息。

          • Historyservice

          Activiti的歷史管理類(lèi),可以查詢(xún)歷史信息,執(zhí)行流程時(shí),引擎會(huì)保存很多數(shù)據(jù)(根據(jù)配置),比如流程實(shí)例啟動(dòng)時(shí)間,任務(wù)的參與者,完成任務(wù)的時(shí)間,每個(gè)流程實(shí)例的執(zhí)行路徑,等等。這個(gè)服務(wù)主要通過(guò)查詢(xún)功能來(lái)獲得這些數(shù)據(jù)。

          • ManagementService

          Activiti的引擎管理類(lèi),提供了對(duì)Activiti流程引擎的管理和維護(hù)功能,這些功能不在工作流驅(qū)動(dòng)的應(yīng)用程序中使用,主要用于Activiti 系統(tǒng)的日常維護(hù)。

          流程圖符號(hào)說(shuō)明

          圖片

          BPMN插件

          使用IDEA進(jìn)行開(kāi)發(fā),建議下載一個(gè)插件。actiBPM插件,直接搜索下載。

          流程符號(hào)、畫(huà)流程圖

          流程符號(hào):事件Event,活動(dòng)Activity,網(wǎng)關(guān)Gateway,流向

          使用流程設(shè)計(jì)器畫(huà)出流程圖

          • 創(chuàng)建bpmn文件,在流程設(shè)計(jì)器使用流程符號(hào)來(lái)表達(dá)流程,指定流程的key,指定任務(wù)負(fù)責(zé)人
          • 生成png文件
          • 創(chuàng)建的bpmn文件要放在resourse下的bpmn文件夾下。

          圖片

          圖片

          注意: 當(dāng)前任務(wù)流程的ID不能是數(shù)字開(kāi)頭。

          圖片

          找到本地的文件,選擇notepad打開(kāi)

          <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
          <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1611283406582" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
            <process id="myEvection" isClosed="false" isExecutable="true" name="出差申請(qǐng)" processType="None">
              <startEvent id="_2" name="StartEvent"/>
              <userTask activiti:assignee="zhangsan" activiti:exclusive="true" id="_3" name="創(chuàng)建出差申請(qǐng)"/>
              <userTask activiti:assignee="jerry" activiti:exclusive="true" id="_4" name="經(jīng)理審批"/>
              <userTask activiti:assignee="jack" activiti:exclusive="true" id="_5" name="總經(jīng)理審批"/>
              <userTask activiti:assignee="rose" activiti:exclusive="true" id="_6" name="財(cái)務(wù)審批"/>
              <endEvent id="_7" name="EndEvent"/>
              <sequenceFlow id="_8" sourceRef="_2" targetRef="_3"/>
              <sequenceFlow id="_9" sourceRef="_3" targetRef="_4"/>
              <sequenceFlow id="_10" sourceRef="_4" targetRef="_5"/>
              <sequenceFlow id="_11" sourceRef="_5" targetRef="_6"/>
              <sequenceFlow id="_12" sourceRef="_6" targetRef="_7"/>
            </process>
            <bpmndi:BPMNDiagram documentation="background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
              <bpmndi:BPMNPlane bpmnElement="myEvection">
                <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
                  <omgdc:Bounds height="32.0" width="32.0" x="185.0" y="0.0"/>
                  <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
                  </bpmndi:BPMNLabel>
                </bpmndi:BPMNShape>
                <bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
                  <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="85.0"/>
                  <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
                  </bpmndi:BPMNLabel>
                </bpmndi:BPMNShape>
                <bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
                  <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="185.0"/>
                  <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
                  </bpmndi:BPMNLabel>
                </bpmndi:BPMNShape>
                <bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
                  <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="285.0"/>
                  <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
                  </bpmndi:BPMNLabel>
                </bpmndi:BPMNShape>
                <bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6">
                  <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="390.0"/>
                  <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
                  </bpmndi:BPMNLabel>
                </bpmndi:BPMNShape>
                <bpmndi:BPMNShape bpmnElement="_7" id="Shape-_7">
                  <omgdc:Bounds height="32.0" width="32.0" x="185.0" y="475.0"/>
                  <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
                  </bpmndi:BPMNLabel>
                </bpmndi:BPMNShape>
                <bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_6" targetElement="_7">
                  <omgdi:waypoint x="201.0" y="445.0"/>
                  <omgdi:waypoint x="201.0" y="475.0"/>
                  <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
                  </bpmndi:BPMNLabel>
                </bpmndi:BPMNEdge>
                <bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_2" targetElement="_3">
                  <omgdi:waypoint x="201.0" y="32.0"/>
                  <omgdi:waypoint x="201.0" y="85.0"/>
                  <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
                  </bpmndi:BPMNLabel>
                </bpmndi:BPMNEdge>
                <bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_3" targetElement="_4">
                  <omgdi:waypoint x="202.5" y="140.0"/>
                  <omgdi:waypoint x="202.5" y="185.0"/>
                  <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
                  </bpmndi:BPMNLabel>
                </bpmndi:BPMNEdge>
                <bpmndi:BPMNEdge bpmnElement="_11" id="BPMNEdge__11" sourceElement="_5" targetElement="_6">
                  <omgdi:waypoint x="202.5" y="340.0"/>
                  <omgdi:waypoint x="202.5" y="390.0"/>
                  <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
                  </bpmndi:BPMNLabel>
                </bpmndi:BPMNEdge>
                <bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_4" targetElement="_5">
                  <omgdi:waypoint x="202.5" y="240.0"/>
                  <omgdi:waypoint x="202.5" y="285.0"/>
                  <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
                  </bpmndi:BPMNLabel>
                </bpmndi:BPMNEdge>
              </bpmndi:BPMNPlane>
            </bpmndi:BPMNDiagram>
          </definitions>

          流程的操作

          部署流程

          使用 Activiti 提供的 API 把流程圖的內(nèi)容寫(xiě)入到數(shù)據(jù)庫(kù)中

          屬于資源操作類(lèi),使用 RepositoryService

          • 單文件部署:把bpmn文件和png文件逐個(gè)處理
          • 壓縮包部署:把bpmn文件和png文件打成壓縮包來(lái)處理
          • 部署操作表:act_re_deployment、act_re_procdef、act_ge_bytearray
          /**
           * 流程部署
           */
          public void deployment() {
              // 創(chuàng)建 ProcessEngine
              ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
              // 獲取 RepositoryService
              RepositoryService repositoryService = processEngine.getRepositoryService();
              // 使用 service 進(jìn)行流程的部署,定義一個(gè)流程的名字,把bpmn和png部署到數(shù)據(jù)中
              Deployment deployment = repositoryService.createDeployment()
                      .name("出差申請(qǐng)流程") //流程圖標(biāo)的名字
                      .addClasspathResource("bpmn/evection.bpmn") //bpmn文件
                      .addClasspathResource("bpmn/evection.png") //bpmn文件生成的圖片
                      .deploy();
              // 輸出部署信息
              System.out.println("流程部署ID:" + deployment.getId());
              System.out.println("流程部署名字:" + deployment.getName());
          }

          有時(shí)候我們會(huì)有多個(gè)流程,需要?jiǎng)?chuàng)建多個(gè)bpmn流程文件,這個(gè)時(shí)候想要同時(shí)部署,我們可以對(duì)bpmn文件進(jìn)行打包壓縮,使用Zip包進(jìn)行批量的部署

          /**
           * 使用Zip包進(jìn)行批量的部署
           */
          @Test
          public void deployProcessByZip() {
              // 獲取流程引擎
              ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
              // 獲取 RepositoryService
              RepositoryService repositoryService = processEngine.getRepositoryService();
              // 流程部署
              // 讀取資源包文件,構(gòu)造成 InputStream
              InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/evection.zip");
              // 使用 InputStream 構(gòu)造 ZipInputStream
              ZipInputStream zipInputStream = new ZipInputStream(inputStream);
              // 使用壓縮包的流,進(jìn)行流程的部署
              Deployment deploy = repositoryService.createDeployment()
                      .addZipInputStream(zipInputStream)
                      .deploy();
              // 輸出
              System.out.println("流程部署的ID:" + deploy.getId());
              System.out.println("流程部署的名稱(chēng):" + deploy.getName());
          }

          操作的數(shù)據(jù)庫(kù)表:

          • act_ge_bytearray
          • act_ge_property
          • act_re_deployment
          • act_re_procdef

          啟動(dòng)流程實(shí)例

          流程部署完成以后,需要啟動(dòng)流程實(shí)例。使用 RuntimeService 根據(jù)流程定義的 key進(jìn)行啟動(dòng)。

          核心代碼:

          /**
           * 啟動(dòng)流程
           */
          public void starProcess() {
              // 創(chuàng)建 ProcessEngine
              ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
              // 獲取 RunTimeService
              RuntimeService runtimeService = processEngine.getRuntimeService();
              // 根據(jù)流程定義的ID啟動(dòng)流程
              ProcessInstance instance = runtimeService.startProcessInstanceByKey("myEvection");
              // 輸出內(nèi)容
              System.out.println("流程定義ID:" + instance.getProcessDefinitionId());
              System.out.println("流程實(shí)例的ID:" + instance.getId());
              System.out.println("當(dāng)前活動(dòng)的ID:" + instance.getActivityId());
          }

          任務(wù)查詢(xún)

          使用 TaskService ,根據(jù)流程定義的 key ,任務(wù)負(fù)責(zé)人來(lái)進(jìn)行查詢(xún)

          核心代碼:

          /**
           * 查詢(xún)個(gè)人待執(zhí)行的任務(wù)
           */
          @Test
          public void findPersonalTaskList() {
              // 獲取流程引擎
              ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
              // 獲取TaskService
              TaskService taskService = processEngine.getTaskService();
              // 根據(jù)流程的key和任務(wù)的負(fù)責(zé)人去查詢(xún)?nèi)蝿?wù)
              List<Task> taskList = taskService.createTaskQuery()
                      .processDefinitionKey("myEvection")  // 流程的key
                      .includeProcessVariables()
                      .taskAssignee("zhangsan")           // 要查詢(xún)的負(fù)責(zé)人
                      .list();
              // 輸出
              for (Task task : taskList) {
                  System.out.println("流程實(shí)例的ID:" + task.getProcessInstanceId());
                  System.out.println("任務(wù)的ID:" + task.getId());
                  System.out.println("任務(wù)的負(fù)責(zé)人:" + task.getAssignee());
                  System.out.println("任務(wù)的名稱(chēng):" + task.getName());
              }
          }

          任務(wù)完成

          使用 TaskService ,用任務(wù) ID 直接完成任務(wù)。

          核心代碼:

          /**
           * 完成個(gè)人任務(wù)
           */
          @Test
          public void completTask() {
              String key = "testCandidiate";
              String assignee = "張三1"; //任務(wù)的負(fù)責(zé)人
              ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
              TaskService taskService = processEngine.getTaskService();
              Task task = taskService.createTaskQuery()
                      .processDefinitionKey(key)
                      .taskAssignee(assignee)
                      .singleResult();
              if (task != null) {
                  taskService.complete(task.getId());
              }
          }

          關(guān)于流程實(shí)例的掛起和激活

          全部流程實(shí)例的掛起和激活

          /**
           * 全部流程實(shí)例的掛起和激活
           */
          @Test
          public void suspendAllProcessInstance() {
              // 1.獲取流程引擎
              ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
              // 2.獲取 RepositoryService
              RepositoryService repositoryService = processEngine.getRepositoryService();
              // 3.查詢(xún)流程定義
              ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                      .processDefinitionKey("myEvection")
                      .singleResult();
              // 4.獲取當(dāng)前流程定義的實(shí)例是否都是掛起狀態(tài)
              boolean flag = processDefinition.isSuspended();
              // 5.獲取流程定義的ID
              String id = processDefinition.getId();
              // 6.判斷是否掛起狀態(tài)。是:改為激活;否:改為掛起
              if (flag) {
                  // 改為激活. 參數(shù)1:流程定義的ID,參數(shù)2:是否激活,參數(shù)3:激活時(shí)間
                  repositoryService.activateProcessDefinitionById(id, true, null);
                  System.out.println("流程定義ID:" + id + "已激活");
              } else {
                  // 改為掛起. 參數(shù)1:流程定義的ID;參數(shù)2:是否掛起;參數(shù)3:掛起時(shí)間
                  repositoryService.suspendProcessDefinitionById(id, true, null);
                  System.out.println("流程定義ID:" + id + "已掛起");
              }
          }

          單個(gè)流程實(shí)例的掛起和激活

          /**
           * 單個(gè)流程實(shí)例的掛起和激活
           */
          @Test
          public void suspendSingleProcessInstance() {
              // 1.獲取流程引擎
              ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
              // 2.獲取 RuntimeService
              RuntimeService runtimeService = processEngine.getRuntimeService();
              // 3.通過(guò) RuntimeService 獲取流程實(shí)例對(duì)象
              ProcessInstance instance = runtimeService.createProcessInstanceQuery()
                      .processInstanceId("17501")
                      .singleResult();
              // 4.得到當(dāng)前流程實(shí)例的暫停狀態(tài)
              boolean flag = instance.isSuspended();
              // 5.獲取流程實(shí)例的ID
              String instanceId = instance.getId();
              // 6.判斷是否暫停。是:改為激活;否:改為暫停
              if (flag) {
                  runtimeService.activateProcessInstanceById(instanceId);
                  System.out.println("流程實(shí)例ID:" + instanceId + "已激活");
              } else {
                  runtimeService.suspendProcessInstanceById(instanceId);
                  System.out.println("流程實(shí)例ID:" + instanceId + "已暫停");
              }
          }

          注意: 流程實(shí)例在掛起的狀態(tài)下是無(wú)法進(jìn)行下一步操作的。

          流程變量

          我們?cè)谑褂昧鞒套兞康臅r(shí)候。如果我們將一個(gè)對(duì)象存儲(chǔ)到一個(gè)流程變量中,那么這個(gè)對(duì)象需要實(shí)現(xiàn)Serializable接口。

          /**
           * 出差申請(qǐng)中的流程變量對(duì)象
           */
          @NoArgsConstructor
          @AllArgsConstructor
          @Data
          public class Evection implements Serializable {

              private Long id;                //主鍵ID
              private Integer days;            //出差天數(shù)
              private String evectionName;    //出差單名字
              private Date startTime;         //出差開(kāi)始時(shí)間
              private Date endTime;           //出差結(jié)束時(shí)間
              private String address;         //目的地
              private String reason;          //出差原因

          }

          流程變量的作用域

          • 整個(gè)流程實(shí)例、任務(wù)、執(zhí)行實(shí)例。
          • 默認(rèn):整個(gè)流程實(shí)例。

          使用方法

          在屬性上使用UEL表達(dá)式 ${assignee}assignee就是一個(gè)流程變量的名稱(chēng)。

          圖片

          在連線(xiàn)上使用UEL表達(dá)式 ${days<=3},days就是一個(gè)流程變量名稱(chēng),返回結(jié)果為true或者false。

          圖片

          Activiti有很多種方式設(shè)置流程變量,這里簡(jiǎn)單介紹兩種:

          啟動(dòng)流程時(shí)設(shè)置流程變量

          /**
           * 啟動(dòng)流程
           */
          @Test
          public void startProcess() {
              ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
              RuntimeService runtimeService = processEngine.getRuntimeService();
              // 流程變量map
              Map<String, Object> map = new HashMap<>();
              // 設(shè)置流程變量
              Evection evection = new Evection();
              evection.setDays(2);
              // 把流程變量的pojo放入map
              map.put("evection", evection);
              map.put("assignee0""張三");
              map.put("assignee1""李經(jīng)理");
              map.put("assignee2""王財(cái)務(wù)");
              map.put("assignee3""趙總經(jīng)理");
              runtimeService.startProcessInstanceByKey("myProcess_1", map);
          }

          任務(wù)辦理時(shí)設(shè)置

          /**
           * 完成任務(wù)
           */
          @Test
          public void completTask() {
              ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
              TaskService taskService = processEngine.getTaskService();
              Evection evection = new Evection();
              evection.setDays(2);
              Map<String, Object> map = new HashMap<>();
              map.put("evection", evection);
              Task task = taskService.createTaskQuery()
                      .processDefinitionKey("myProcess_2")
                      .taskAssignee("王財(cái)務(wù)0")
                      .singleResult();
              if (task != null) {
                  String taskId = task.getId();
                  // 完成任務(wù)
                  taskService.complete(taskId, map);
              }
          }

          網(wǎng)關(guān)

          用來(lái)控制流程的走向

          排他網(wǎng)關(guān)——ExclusiveGateway

          用來(lái)在流程中實(shí)現(xiàn)決策,當(dāng)流程執(zhí)行到這個(gè)網(wǎng)關(guān),所有的分支都會(huì)判斷條件是否為true,如果為true,則執(zhí)行該分支。

          注意: 排他網(wǎng)關(guān)只會(huì)選擇一個(gè)作為true的分支執(zhí)行,如果有兩個(gè)分支都為true,排他網(wǎng)關(guān)會(huì)選擇ID值比較小的一條分支去執(zhí)行。

          如果從排他網(wǎng)關(guān)出去的流程所有的條件都不滿(mǎn)足,則會(huì)拋出異常。

          并行網(wǎng)關(guān)——ParallelGateway

          并行網(wǎng)關(guān),允許流程分成多條分支,也可以把多分支匯聚到一起,并行網(wǎng)關(guān)的功能是基于進(jìn)入和外出順序流的:

          • fork分支:并行后的所有外出順序流,為每個(gè)順序流都創(chuàng)建一個(gè)并發(fā)分支
          • join匯聚:所有到達(dá)并行網(wǎng)關(guān),在此等待的分支,直到所有進(jìn)入順序流的分支都到達(dá)以后,流程就會(huì)通過(guò)匯聚網(wǎng)關(guān)。

          注意: 如果同一個(gè)并行網(wǎng)關(guān)有多個(gè)進(jìn)入和多個(gè)外出順序流,它就同時(shí)具有分支和匯聚功能,這時(shí),網(wǎng)關(guān)會(huì)先匯聚所有進(jìn)入的順序流,然后再切分成多個(gè)并行分支。

          與其他網(wǎng)關(guān)的主要區(qū)別是:并行網(wǎng)關(guān)不會(huì)解析條件,即使順序流中定義了條件,也會(huì)被忽略。

          并行網(wǎng)關(guān)需要所有分支的全部運(yùn)行完了,才會(huì)匯聚,繼續(xù)向下執(zhí)行。

          包含網(wǎng)關(guān)——InclusiveGateway

          包含網(wǎng)關(guān)可以看成是排他網(wǎng)關(guān)和并行網(wǎng)關(guān)的結(jié)合體,和排他網(wǎng)關(guān)一樣,可以在外出順序流上定義條件,包含網(wǎng)關(guān)會(huì)解析它們,但是主要的區(qū)別是:包含網(wǎng)關(guān)可以選擇多于一條順序流,這和并行網(wǎng)關(guān)一樣。

          包含網(wǎng)關(guān)的功能是基于進(jìn)入和外出順序流的。

          • 分支:所有外出順序流的條件都會(huì)被解析,結(jié)果為true的順序流會(huì)以并行方式繼續(xù)執(zhí)行,會(huì)為每一個(gè)順序流創(chuàng)建一個(gè)分支。
          • 匯聚:所有并行分支到達(dá)包含網(wǎng)關(guān),會(huì)進(jìn)入等待狀態(tài),直到每個(gè)包含流程token的進(jìn)入順序流的分支都到達(dá)。這是和并行網(wǎng)關(guān)最大的不同。

          事件網(wǎng)關(guān)——EventGateway

          Activiti和Spring的整合開(kāi)發(fā)

          配置文件:

          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:tx="http://www.springframework.org/schema/tx"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans
                  http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                   http://www.springframework.org/schema/tx
                  http://www.springframework.org/schema/tx/spring-tx.xsd"
          >

              <!--工作流引擎配置對(duì)象-->
              <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
                  <!--數(shù)據(jù)源-->
                  <property name="dataSource" ref="dataSource"/>
                  <!--使用Spring的事務(wù)管理器-->
                  <property name="transactionManager" ref="transactionManager"/>
                  <!--
                  數(shù)據(jù)庫(kù)策略:
                      false:默認(rèn)值。activiti在啟動(dòng)時(shí),會(huì)對(duì)比數(shù)據(jù)庫(kù)表中保存的版本。如果沒(méi)有表或者版本不匹配,將拋出     異常。
                      true:activiti會(huì)對(duì)數(shù)據(jù)庫(kù)中所有表進(jìn)行更新操作,如果表不存在,則會(huì)自動(dòng)創(chuàng)建。
                      create_drop:在activiti啟動(dòng)時(shí)創(chuàng)建表,在關(guān)閉時(shí)刪除表(必須手動(dòng)關(guān)閉引擎,才能刪除表)。
                      drop-create:在activiti啟動(dòng)時(shí)刪除原來(lái)的舊表,然后再創(chuàng)建新表(不需要手動(dòng)關(guān)閉引擎)。
                  -->
                  <property name="databaseSchemaUpdate" value="true"/>
              </bean>

              <!--配置數(shù)據(jù)源-->
              <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
                  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                  <property name="url" value="jdbc:mysql://localhost:3306/actspring"/>
                  <property name="username" value="root"/>
                  <property name="password" value="root"/>
                  <property name="maxActive" value="3"/>
                  <property name="maxIdle" value="1"/>
              </bean>

              <!-- 流程引擎對(duì)象 -->
              <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
                  <property name="processEngineConfiguration" ref="processEngineConfiguration"/>
              </bean>

              <!--資源服務(wù)-->
              <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/>
              <!--流程管理-->
              <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
              <!--任務(wù)管理-->
              <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/>
              <!--歷史管理-->
              <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/>

              <!--事務(wù)管理器-->
              <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                  <property name="dataSource" ref="dataSource"/>
              </bean>

              <!--通知-->
              <tx:advice id="txAdvice" transaction-manager="transactionManager">
                  <tx:attributes>
                      <!--傳播行為-->
                      <tx:method name="save*" propagation="REQUIRED"/>
                      <tx:method name="insert*" propagation="REQUIRED"/>
                      <tx:method name="delete*" propagation="REQUIRED"/>
                      <tx:method name="update*" propagation="REQUIRED"/>
                      <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
                      <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
                  </tx:attributes>
              </tx:advice>
          </beans>
          Activiti和SpringBoot的整合開(kāi)發(fā)

          配置文件:

          spring:
            application:
              name: actspringboot
            datasource:
              driver-class-name: com.mysql.jdbc.Driver
              url: jdbc:mysql://localhost:3306/actspring?useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true&serverTimezone=UTC
              username: root
              password: root
            activiti:
              # false:默認(rèn)值。activiti在啟動(dòng)時(shí),會(huì)對(duì)比數(shù)據(jù)庫(kù)表中保存的版本。如果沒(méi)有表或者版本不匹配,將拋出異常
              # true:activiti會(huì)對(duì)數(shù)據(jù)庫(kù)中所有表進(jìn)行更新操作,如果表不存在,則會(huì)自動(dòng)創(chuàng)建
              # create_drop:在activiti啟動(dòng)時(shí)創(chuàng)建表,在關(guān)閉時(shí)刪除表(必須手動(dòng)關(guān)閉引擎,才能刪除表)
              # drop-create:在activiti啟動(dòng)時(shí)刪除原來(lái)的舊表,然后再創(chuàng)建新表(不需要手動(dòng)關(guān)閉引擎)
              # 線(xiàn)上一般使用false,開(kāi)發(fā)中使用true
              database-schema-update: true
              # 自動(dòng)部署驗(yàn)證設(shè)置:true-開(kāi)啟(默認(rèn))、false-關(guān)閉
              check-process-definitions: false
              # 開(kāi)啟歷史表
              db-history-used: true
              # 歷史記錄存儲(chǔ)等級(jí)
              history-level: full
          server:
            port: 8082

          瀏覽 54
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久热中文字幕 | 午夜色综合 | 美女大香蕉久久 | 国产一a毛一a毛A免费看图 | 欧美国产精品一区婷婷五月天 |