<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      最近進行的一次技術(shù)選型(工作流引擎)及相關(guān)知識介紹

      前言

      最近有個新項目,需要實現(xiàn)類似工作流引擎的效果,如果不知道是啥,看完本文就懂了。
      公司內(nèi)其實也有些自研的,可能就是不像開源的這些那樣,還支持這個那個規(guī)范,都是基于需求定制開發(fā)的,擴展性稍微差點。
      所以,這次其實幾個同事,分工調(diào)研了幾個開源的和公司內(nèi)的,開源的包括activiti、flowable、camunda,我這邊主要調(diào)研了flowable、camunda,同事調(diào)研了activiti和公司內(nèi)部的。

      最終看下來,我們的需求,其實不需要用到這么復雜的開源框架,公司內(nèi)的一個框架更符合一些。開源的框架,會建很多表,表也不符合公司內(nèi)的建表規(guī)范,所以還需要閱讀源碼,去改造之類的,也比較麻煩。會引入很多jar包,總體來說,還是比較重。

      文末有幾個引擎的對比,大家有興趣可以看看,也可以加我微信和我探討(只花了兩天時間,可能也了解得也比較粗略)。

      最終來說,技術(shù)還是服務(wù)于需求的,不是因為框架牛逼就硬上,合適最重要。

      先說說uml和omg

      學過軟件工程的同學,肯定知道uml,全稱Unified Modeling Language,統(tǒng)一建模語言。建模,為啥要建模,因為軟件研發(fā)過程較為抽象,一個需求來了,肯定要先分析分析,建個模(通俗就是:畫個圖),但是每個人畫出來的圖都不一樣,比如uml里用一個小人來表示用戶,有的人就不愿意用小人。所以,為了業(yè)界內(nèi)人士溝通交流更方便,就定義了一套標準,每種圖應該怎么畫,包含了哪些部分。

      比如uml包含了如下類型的圖,每種圖里,都有固定的圖例來代表固定的意思(僅部分):

      ok,大家明白了uml,我再說說omg是啥,omg是個標準化組織,致力于提出uml這樣類似的標準,和業(yè)界的公司進行討論交流,各公司的人、學術(shù)界的人、omg的人,共同討論,提出一個大家都能接受的方案,然后大家就按照這個標準來進行實現(xiàn)。

      世界上的標準化機構(gòu)很多,omg手里拿出來的,現(xiàn)在廣為使用的,被iso采納的,有如下幾個。

      主要就是uml和bpmn,注意,沒有xml(圖里右上角那個是xmi)。

      bpmn

      圖形規(guī)范

      bpmn(Business Process Model And Notation)是啥,也是一種建模語言,和uml類似,就是規(guī)定:xxx,用這個來表示,yyy,用那個來表示。

      bpmn主要是對工作流進行建模,大家公司里的oa系統(tǒng),基本就是工作流的典范,比如下面這樣一個用戶請假流程,就是遵循bpmn規(guī)范的。

      這個圖里,哪些地方用空心圓,哪些地方是矩形,哪些地方用菱形,都是有講究,這就是bpmn規(guī)范里定義的。

      xml規(guī)范

      bpmn對圖形有規(guī)范,對圖形背后的存儲格式也有定義,這個圖,最終會轉(zhuǎn)化為一份xml,這份xml也是遵循特定的schema的。

      上圖這個xml,就是遵循omg官方的schema,里面最外層是一個process元素,里面的元素則只能是startEvent、sequenceFlow等。

      這樣標準化了之后,業(yè)界各個廠商,就可以各自開發(fā)一套實現(xiàn),只要這套實現(xiàn),最終能生成上面這樣的xml,那就是符合bpmn的,拿這份bpmn文件到其他廠商那里,其他廠商的程序也能正確解析該文件,因此就實現(xiàn)了互聯(lián)互通,這就是標準的力量。

      bpmn版本歷史

      主要是4個版本,現(xiàn)在業(yè)界基本都是基于2010年的最新版本2.0進行實現(xiàn),也就是bpmn2.0

      VERSION ADOPTION DATE URL
      2.0 十二月 2010 https://www.omg.org/spec/BPMN/2.0/
      1.2 一月 2009 https://www.omg.org/spec/BPMN/1.2/
      1.1 一月 2008 https://www.omg.org/spec/BPMN/1.1/
      1.0 三月 2007 https://www.omg.org/spec/BPMN/1.0/

      bpmn 2.0的業(yè)界實現(xiàn)

      實現(xiàn)還是挺多的,近10多個。現(xiàn)在大家比較用得多的,還是紅框的幾個,Activiti、Camunda、Flowable、jBPM。

      這些實現(xiàn),互相有些關(guān)系,就像log4j的維護人后來又創(chuàng)建了logback一樣。

      目前主要就是在 Camunda/flowable 6/ activiti里面去選擇。

      flowable 內(nèi)嵌模式快速了解

      創(chuàng)建maven工程(文末有代碼)

      如果一上來,直接就開始比較各框架的差異,大家由于對其中任意一個都不了解,所以也沒法參照。這里先講一下flowable框架(目前最先了解這個框架)。

      flowable 引擎,支持兩種運行模式,一種是內(nèi)嵌到業(yè)務(wù)服務(wù)中,咱們先講這種。

      先建一個普通的maven工程,加入flowable引擎的依賴以及h2內(nèi)嵌數(shù)據(jù)庫的依賴(正式項目會換成mysql等持久化數(shù)據(jù)庫)

          <!-- https://mvnrepository.com/artifact/org.flowable/flowable-engine -->
          <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-engine</artifactId>
            <version>6.7.2</version>
          </dependency>
          <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.192</version>
          </dependency>
      

      創(chuàng)建流程引擎實例

      以下,先創(chuàng)建一個引擎實例出來:

      
      import org.flowable.engine.ProcessEngine;
      import org.flowable.engine.ProcessEngineConfiguration;
      import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
      
      public class HolidayRequest {
      
        public static void main(String[] args) {
          ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
            .setJdbcUrl("jdbc:h2:mem:flowable;DB_CLOSE_DELAY=-1")
            .setJdbcUsername("sa")
            .setJdbcPassword("")
            .setJdbcDriver("org.h2.Driver")
            .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
      
          ProcessEngine processEngine = cfg.buildProcessEngine();
        }
      
      }
      

      接下來,我們就可以往這個引擎實例上部署一個流程xml。比如,假設(shè)我們最終想建立一個員工請假流程,那么,我們可以通過各種辦法(如flowable自帶的web-ui拖拽的方式或手動創(chuàng)建xml等),來建立一個下面這樣的,符合bpmn2.0規(guī)范的流程定義xml(holiday-request.bpmn20.xml)。

      <?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:activiti="http://activiti.org/bpmn"
                   typeLanguage="http://www.w3.org/2001/XMLSchema"
                   expressionLanguage="http://www.w3.org/1999/XPath"
                   targetNamespace="http://www.flowable.org/processdef">
      
          <process id="holidayRequest" name="Holiday Request" isExecutable="true">
      
              <startEvent id="startEvent"/>
              <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>
      
      <!--        <userTask id="approveTask" name="Approve or reject request"/>-->
              <userTask id="approveTask" name="Approve or reject request" activiti:candidateGroups="managers"/>
      
              <sequenceFlow sourceRef="approveTask" targetRef="decision"/>
      
              <exclusiveGateway id="decision"/>
              <sequenceFlow sourceRef="decision" targetRef="externalSystemCall">
                  <conditionExpression xsi:type="tFormalExpression">
                      <![CDATA[
                ${approved}
              ]]>
                  </conditionExpression>
              </sequenceFlow>
              <sequenceFlow sourceRef="decision" targetRef="sendRejectionMail">
                  <conditionExpression xsi:type="tFormalExpression">
                      <![CDATA[
                ${!approved}
              ]]>
                  </conditionExpression>
              </sequenceFlow>
      
              <serviceTask id="externalSystemCall" name="Enter holidays in external system"
                           activiti:class="org.example.CallExternalSystemDelegate"/>
              <sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/>
      
      <!--        <userTask id="holidayApprovedTask" name="Holiday approved"/>-->
              <userTask id="holidayApprovedTask" name="Holiday approved" activiti:assignee="${employee}"/>
      
              <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>
      
              <serviceTask id="sendRejectionMail" name="Send out rejection email"
                           activiti:class="org.flowable.SendRejectionMail"/>
              <sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>
      
              <endEvent id="approveEnd"/>
      
              <endEvent id="rejectEnd"/>
      
          </process>
      
      </definitions>
      

      這個xml是不是比較抽象?這個xml就類似于一種標準格式,就像java的class文件一樣,實現(xiàn)跨平臺的效果。

      該xml對應的流程圖如下:

      接下來,我們就把這個文件,傳給流程引擎,讓它基于該文件,創(chuàng)建一個工作流。

      RepositoryService repositoryService = processEngine.getRepositoryService();
      Deployment deployment = repositoryService.createDeployment()
        .addClasspathResource("holiday-request.bpmn20.xml")
        .deploy();
      

      創(chuàng)建后,實際就寫到內(nèi)存數(shù)據(jù)庫h2了,此時,我們還可以把它查出來

      ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
        .deploymentId(deployment.getId())
        .singleResult();
      System.out.println("Found process definition : " + processDefinition.getName());
      

      創(chuàng)建工作流實例

      工作流實例,一開始需要一些輸入?yún)?shù),員工不是需要請假嗎,我們就需要:員工姓名、請假天數(shù)、事由等。

      Scanner scanner= new Scanner(System.in);
      
      System.out.println("Who are you?");
      String employee = scanner.nextLine();
      
      System.out.println("How many holidays do you want to request?");
      Integer nrOfHolidays = Integer.valueOf(scanner.nextLine());
      
      System.out.println("Why do you need them?");
      String description = scanner.nextLine();
      
      
      RuntimeService runtimeService = processEngine.getRuntimeService();
      
      Map<String, Object> variables = new HashMap<String, Object>();
      variables.put("employee", employee);
      variables.put("nrOfHolidays", nrOfHolidays);
      variables.put("description", description);
      
      

      ok,參數(shù)準備好了,就準備傳給工作流了:

      ProcessInstance processInstance =
          runtimeService.startProcessInstanceByKey("holidayRequest", variables);
      

      此時,就會根據(jù)流程定義里的:

      <userTask id="approveTask" name="Approve or reject request" activiti:candidateGroups="managers"/>
      

      創(chuàng)建一個任務(wù),任務(wù)有個標簽,就是candidate group,這里是manager,可以猜得出,是給manager建了個審批任務(wù)。

      manager查詢并審批任務(wù)

      以下,基于manager查詢?nèi)蝿?wù):

      TaskService taskService = processEngine.getTaskService();
      List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("managers").list();
      System.out.println("You have " + tasks.size() + " tasks:");
      for (int i=0; i<tasks.size(); i++) {
        System.out.println((i+1) + ") " + tasks.get(i).getName());
      }
      

      我們可把任務(wù)打印出來看看:

      System.out.println("Which task would you like to complete?");
      int taskIndex = Integer.valueOf(scanner.nextLine());
      Task task = tasks.get(taskIndex - 1);
      Map<String, Object> processVariables = taskService.getVariables(task.getId());
      System.out.println(processVariables.get("employee") + " wants " +
          processVariables.get("nrOfHolidays") + " of holidays. Do you approve this?");
      

      審批任務(wù):

      boolean approved = scanner.nextLine().toLowerCase().equals("y");
      variables = new HashMap<String, Object>();
      variables.put("approved", approved);
      taskService.complete(task.getId(), variables);
      

      這里就是把全局變量 approved,設(shè)為了true,然后提交給引擎。引擎就會根據(jù)這里的變量為true還是false,走不同分支。對應了:

      回調(diào)用戶代碼--用戶開始休假

      上面審批后,就會進入下一個節(jié)點:休假。

      <serviceTask id="externalSystemCall" name="Enter holidays in external system"
                   activiti:class="org.example.CallExternalSystemDelegate"/>
      
      

      這里有個class,就是需要我們自己實現(xiàn)的。

      然后,基本流程就自己走完了。

      flowable rest-api模式

      簡介

      上面那種,是其作為一個jar,內(nèi)嵌到我們的程序里,創(chuàng)建引擎對下。由我們業(yè)務(wù)程序去驅(qū)動引擎的運行。引擎和業(yè)務(wù)代碼在同一個進程。

      其實,flowable也可以作為一個獨立服務(wù)運行,提供rest-api出來,這樣的話,非java語言的開發(fā)者也可以使用該引擎了。

      這個只需要我們下載官方的zip包,里面有個rest的war包,我們丟到tomcat里運行。

      上傳工作流定義xml文件,部署工作流

      如果要實現(xiàn)上面java-api那樣的功能,我們就需要調(diào)接口來實現(xiàn)

      下面就開始啟動工作流:

      其他接口就不一一展示了。可以參考文檔。

      flowable-ui,通過web ui進行流程xml建模

      上面手工建立xml,還是比較累的,我們可以通過其提供的web ui來建模,省點力氣。(不過也不是很好用,各種名詞比較費解,大家可能還是要自己做一套前端界面,調(diào)用自己的接口,來生成一個xml文件)

      上面的rest那一節(jié),tomcat里就部署了一個flowable-ui的。

      就可以通過下面這樣的方式來建模。

      其他方面

      活躍程度:activiti是最活躍的,activiti (非常活躍,一天一個alpha版本)> camunda(一個月一個alpha版本) > flowable(幾個月或半年一個版本)
      依賴:會引入37個jar包,當前最新的6.7.2版本
      mysql:核心建表語句為7張,歷史表5張;程序運行后,結(jié)果有47張表,具體原因暫時沒去研究
      持久層框架:寫mysql表時,使用mybatis

      引擎對比

      總結(jié)

      demo代碼:
      https://gitee.com/ckl111/all-simple-demo-in-blog/tree/master/flowable-test

      posted @ 2022-03-04 12:56  三國夢回  閱讀(7437)  評論(3)    收藏  舉報
      主站蜘蛛池模板: 樱花草视频www日本韩国| 国产精品免费看久久久| 久久久综合香蕉尹人综合网 | 中文字幕有码高清日韩| 成年女性特黄午夜视频免费看| 他掀开裙子把舌头伸进去添视频 | 无码午夜福利片| 老色鬼永久精品网站| 成人av午夜在线观看| 亚洲欧美日韩国产精品专区| 国产午夜精品福利视频| 中文无码热在线视频| 久久国语对白| 成人小说亚洲一区二区三区| 国产黄大片在线观看画质优化 | 国产亚洲精品久久久久5区| 亚洲av色精品一区二区| 罗甸县| 久久精品国产亚洲成人av| 国产午夜福利在线视频| 69天堂人成无码免费视频| 日韩中文日韩中文字幕亚| 久操资源站| 欧产日产国产精品精品| 欧美寡妇xxxx黑人猛交| 久久综合免费一区二区三区| 国产精品99中文字幕| 亚洲卡1卡2卡新区网站| 免费观看国产女人高潮视频| 亚洲中文字幕在线观看| 国产区精品视频自产自拍| 通州区| 国产精品区一区第一页| 久章草这里只有精品| 在线视频中文字幕二区| 久久www免费人成一看片| 狠狠躁日日躁夜夜躁欧美老妇 | 欧美做受视频播放| 日韩在线视频网| 久久精品女人的天堂av| 免费特黄夫妻生活片|