1. 程式人生 > >activiti節點跳轉

activiti節點跳轉

分享牛原創(尊重原創 轉載對的時候第一行請註明,轉載出處來自分享牛http://blog.csdn.net/qq_30739519)

activiti使用的時候,通常需要跟業務緊密的結合在一起,有些業務非常的複雜,比如一個簡單的採購流程:流程如下:

 

供應商上新商品的時候,提交商務稽核,商務稽核通過提交運營稽核,稽核失敗退回供應商。

運營稽核成功提交合同簽訂。交運營稽核稽核失敗退回商務稽核或者直接退回供應商。

合同簽訂稽核通過結束,合同簽訂稽核不通過返回運營稽核或者退回商務稽核,或者退回供應商。

上面的流程就出現了一個問題,什麼問題呢?

我們來觀察一下退回線的問題。

1.商務稽核退回供應商上新。

2.運營稽核可能退回商務稽核,運營稽核可能退回供應商上新。

3.合同簽訂可能退回運營稽核,合同簽訂可能退回商務稽核,合同簽訂可能退回供應商上新。

4....

假如以後我們的流程在新增新的部門稽核,是不是我們的退回線更加的多了。其實就是n!的問題,難道我們沒新增一個節點,就要畫很多的退回線嗎?這顯然是一個糟糕的設計。oh my god.

存在的問題就是,我們要是想讓我們的流程更加的通用,我們可能在設計的時候,需要新增很多的退回線控制,防止業務變化,流程跟起來變化,這就是應對了變化,同時在增加了冗餘設計。

那有沒有一種更好的方式,能解決上面的問題呢?很顯然這就是我們本章要解決的問題。

1.1.1. activiti節點跳轉實現

實現之前,我們考慮幾個問題。

1.當前流程在哪一個節點。

2.流程需要跳轉的目標節點。

3.跳轉到目標節點之後,需要新增變數嗎?有可能需要把,總不能無緣無故的跳轉到了目標節點。痕跡肯定要記錄。

4.跳轉到目標節點,那當前節點配置的任務監聽需要觸發嗎?(可參考 activiti監聽器使用).當前節點跳轉到目標節點的時候,如果當前節點配置了任務監聽業務,調轉到目標節點之前,這些當前的任務節點的是否觸發任務監聽業務必須能支援靈活配置。

上面的思考點,也是我們接下來需要重點講解的內容。那下面就開始我們的設計吧。

1.1.1.1. 流程圖

下面我們先定義一個流程如下圖所示:

 

1.1.1.2. xml

下面我們先定義一個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: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="daling">
  <process id="daling" name="name_daling" isExecutable="true" activiti:candidateStarterUsers="a,b,c,d">
    <userTask id="usertask2" name="usertask2" activiti:assignee="c"></userTask>
    <userTask id="usertask3" name="usertask3"></userTask>
    <sequenceFlow id="flow4" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>
    <userTask id="usertask4" name="usertask4"></userTask>
    <sequenceFlow id="flow5" sourceRef="usertask3" targetRef="usertask4"></sequenceFlow>
    <userTask id="usertask5" name="usertask5"></userTask>
    <sequenceFlow id="flow6" sourceRef="usertask4" targetRef="usertask5"></sequenceFlow>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow7" sourceRef="usertask5" targetRef="endevent1"></sequenceFlow>
    <startEvent id="startevent1" name="Start"></startEvent>
    <sequenceFlow id="flow8" sourceRef="startevent1" targetRef="usertask2"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_daling">
    <bpmndi:BPMNPlane bpmnElement="daling" id="BPMNPlane_daling">
      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
        <omgdc:Bounds height="55.0" width="105.0" x="300.0" y="90.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
        <omgdc:Bounds height="55.0" width="105.0" x="450.0" y="90.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask4" id="BPMNShape_usertask4">
        <omgdc:Bounds height="55.0" width="105.0" x="600.0" y="90.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask5" id="BPMNShape_usertask5">
        <omgdc:Bounds height="55.0" width="105.0" x="750.0" y="90.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="900.0" y="100.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="140.0" y="90.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
        <omgdi:waypoint x="405.0" y="117.0"></omgdi:waypoint>
        <omgdi:waypoint x="450.0" y="117.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
        <omgdi:waypoint x="555.0" y="117.0"></omgdi:waypoint>
        <omgdi:waypoint x="600.0" y="117.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
        <omgdi:waypoint x="705.0" y="117.0"></omgdi:waypoint>
        <omgdi:waypoint x="750.0" y="117.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
        <omgdi:waypoint x="855.0" y="117.0"></omgdi:waypoint>
        <omgdi:waypoint x="900.0" y="117.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
        <omgdi:waypoint x="175.0" y="107.0"></omgdi:waypoint>
        <omgdi:waypoint x="300.0" y="117.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>


1.1.1.3. 程式碼實現

package com.daling.ch1.jd;
import java.util.Iterator;
import java.util.Map;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityManager;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
 
/**
 *
 * JD節點的跳轉
 * 分享牛原創(尊重原創 轉載對的時候第一行請註明,轉載出處來自分享牛http://blog.csdn.net/qq_30739519)
 */
public class JDJumpTaskCmd implements Command<Void> {
protected String executionId;
protected ActivityImpl desActivity;
protected Map<String, Object> paramvar;
protected ActivityImpl currentActivity;
/**
 * 分享牛原創(尊重原創 轉載對的時候第一行請註明,轉載出處來自分享牛http://blog.csdn.net/qq_30739519)
 */
public Void execute(CommandContext commandContext) {
ExecutionEntityManager executionEntityManager = Context
.getCommandContext().getExecutionEntityManager();
// 獲取當前流程的executionId,因為在併發的情況下executionId是唯一的。
ExecutionEntity executionEntity = executionEntityManager
.findExecutionById(executionId);
executionEntity.setVariables(paramvar);
executionEntity.setEventSource(this.currentActivity);
executionEntity.setActivity(this.currentActivity);
// 根據executionId 獲取Task
Iterator<TaskEntity> localIterator = Context.getCommandContext()
.getTaskEntityManager()
.findTasksByExecutionId(this.executionId).iterator();
 
while (localIterator.hasNext()) {
TaskEntity taskEntity = (TaskEntity) localIterator.next();
// 觸發任務監聽
taskEntity.fireEvent("complete");
// 刪除任務的原因
Context.getCommandContext().getTaskEntityManager()
.deleteTask(taskEntity, "completed", false);
}
executionEntity.executeActivity(this.desActivity);
return null;
}
 
/**
 * 構造引數 可以根據自己的業務需要新增更多的欄位
 * 分享牛原創(尊重原創 轉載對的時候第一行請註明,轉載出處來自分享牛http://blog.csdn.net/qq_30739519)
 * @param executionId
 * @param desActivity
 * @param paramvar
 * @param currentActivity
 */
public JDJumpTaskCmd(String executionId, ActivityImpl desActivity,
Map<String, Object> paramvar, ActivityImpl currentActivity) {
this.executionId = executionId;
this.desActivity = desActivity;
this.paramvar = paramvar;
this.currentActivity = currentActivity;
}
}

1.1.1.4. 使用

我們先讓流程運轉到usertask3節點的時候開始測試跳轉。

怎麼使用上面的JDJumpTaskCmd類呢,直接new JDJumpTaskCmd()呼叫,肯定不行了,因為activiti引擎程式沒有獲取,肯定報錯,正確的的使用方式如下:

1.1.1.4.1. 第一種方式

我們先來觀察一下資料庫ACT_RU_TASK表任務的記錄資訊,方便我們的操作,資料庫記錄如下圖所示:

 

可以看到當前的節點在usertask3,我們現在把usertask3跳轉到usertask5節點,看是否能成功,因為usertask3usertask5沒有連線,如果成功了,就說明我們這個方法正確。

執行下面的程式碼,根據自己的資料庫資訊修改相對應的值即可。

Map<String, Object> vars = new HashMap<String, Object>();
String[] v = { "shareniu1", "shareniu2", "shareniu3", "shareniu4" };
vars.put("assigneeList", Arrays.asList(v));
//分享牛原創(尊重原創 轉載對的時候第一行請註明,轉載出處來自分享牛http://blog.csdn.net/qq_30739519)
RepositoryService repositoryService = demo.getRepositoryService();
ReadOnlyProcessDefinition processDefinitionEntity = (ReadOnlyProcessDefinition) repositoryService
.getProcessDefinition("daling:29:137504");
// 目標節點
ActivityImpl destinationActivity = (ActivityImpl) processDefinitionEntity
.findActivity("usertask5");
String executionId = "137509";
// 當前節點
   ActivityImpl currentActivity = (ActivityImpl)processDefinitionEntity
      .findActivity("usertask3");
demo.getManagementService().executeCommand(
new JDJumpTaskCmd(executionId, destinationActivity, vars,
currentActivity));

執行上面的程式碼之後,我們看一下資料庫中的記錄。

 

節點確實跳轉到了usertask5ok了這個方法確實可以沒問題,下面說一下第二種方式執行executeCommand命令。

1.1.1.4.2. 第二種方式
Map<String, Object> vars = new HashMap<String, Object>();
String[] v = { "shareniu1", "shareniu2", "shareniu3", "shareniu4" };
vars.put("assigneeList", Arrays.asList(v));
//分享牛原創(尊重原創 轉載對的時候第一行請註明,轉載出處來自分享牛http://blog.csdn.net/qq_30739519)
    CommandExecutor commandExecutor = taskServiceImpl
      .getCommandExecutor();
    commandExecutor.execute(new JDJumpTaskCmd(executionId,
      destinationActivity, vars, currentActivity));

上面的兩種方式都可以執行自定義的Command子類。讀者選擇自己喜歡使用的方式即可。

1.1.2. 小結

1.任意節點的跳轉,前提是節點必須在模板定義中。

2.任意節點的跳轉暫時不能跨流程跳轉。

3.任意節點的跳轉不需要連線即可、

4.任意節點的跳轉可以實現回退、轉辦、轉閱、越級上報、一步到底等等功能,關於這些更多的實戰,我們將在最後的工作流實戰專案中一步步封裝。使用。

分享牛原創(尊重原創 轉載對的時候第一行請註明,轉載出處來自分享牛http://blog.csdn.net/qq_30739519)

分享牛,分享、我們是快樂的。

相關推薦

activiti節點

分享牛原創(尊重原創 轉載對的時候第一行請註明,轉載出處來自分享牛http://blog.csdn.net/qq_30739519)activiti使用的時候,通常需要跟業務緊密的結合在一起,有些業務非常的複雜,比如一個簡單的採購流程:流程如下: 供應商上新商品的時候,提交商

Activiti到工作流的任意節點(本例用到上一節點講解即流程回退)

所有用到的service以及實現類都是工作流(Activiti)本身的。 public String taskRollback(String taskId){ //根據要跳轉的任務ID獲取

Activiti+Springboot到任意節點

1.TaskFlowControlService 方法類 package com.epf.activiti.service; import java.util.ArrayList; import java.util.List; import ja

activiti靈活駁回回退操作動態修改流程

import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream;

Activiti 節點

package com.Deer.activiti; import java.util.Iterator; import java.util.Map; import org.activiti.engine.impl.interceptor.Command; import org.activiti

擴充套件Activiti-5.12輕鬆實現流程節點間自由和任意駁回/撤回

由於專案需要,最近對開源工作流引擎Activiti-5.12的功能做了一下擴充套件,實現了以下功能: 1.自由流(流程節點間自由跳轉和任意駁回/撤回) 2.流程會籤任務串並行模式切換 一、自由流在已有流程模型的的基礎上,每個流程例項當前任務可以任意駁回/撤回或者向後續節點任

優雅的實現Activiti動態調整流程(自由、前進、後退、分裂、前加簽、後加籤等),含範例程式碼!

最近對Activiti做了一些深入的研究,對Activiti的流程機制有了些理解,對動態調整流程也有了一些實踐方法。現在好好總結一下,一來是對這段時間自己辛苦探索的一個記錄,二來也是為後來者指指路~~~如下內容準備採用QA的方式寫,很多問題都是當初自己極疑惑的問題,希望能為大

activiti 流程圖點選進行流程(簡易流程可行)

上午寫了篇關於流程執行中高亮顯示當前節點的文件,下午想到了朋友之前提供的demo,於是研究了下流程圖直接點選進行流程跳轉的操作。 當然,只是大概研究了下,搞懂原理後就沒有深入實現了,所以大概說下步驟。 1、獲取所有節點資訊 ProcessDefinitionEntity d

【iOS開發-79】利用Modal方式實現控制器之間的

article 運用 mis cli 控制 present 沒有 dismiss 導航控制器 利用Modal方法。事實上就是以下兩個方法的運用。Modal方式的切換效果是從底部呈現。 -(void)clickModal{ WPViewController *wp

JavaScript基礎 a標記 使用onclick事件阻止默認 onclick事件 與 ,onclick事件優先執行。

傳智 技術部 推薦 turn utf 傳智播客 ctype div type 鎮場詩:    清心感悟智慧語,不著世間名與利。學水處下納百川,舍盡貢高我慢意。    學有小成返哺根,願鑄一良心博客。誠心於此寫經驗,願見文者得啟發。—————————————————————

META http-equiv="refresh" 實現網頁自動

知識 meta head 網頁 src title dot shu 知識庫 使用說明: < HEAD> < TITLE>刷新內容< /TITLE> < META HTTP-EQUIV="REFRESH" CONTENT="x; UR

AngularJS路由實現單頁面

href vid 左邊欄 ref 按順序 -1 生活用品 func 為我 <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <titl

點擊鏈接如何直接到相對應的聊天窗口

pan 臨時 在線 顯示 net 電腦 str 全部 徹底 解決這個問題的步驟如下: 一、登陸騰訊官方網站:http://wp.qq.com/ 二、登陸之後,點“設置”,按下圖所示,全部打勾。這個必須設置,不設置,不能臨時會話,就會顯示“未啟用”。這一步是關

解決出現 No input file specified.

yml follow options rule input ces 跳轉 file engine 項目根目錄中.htaccess文件修改為: <IfModule mod_rewrite.c> Options +FollowSymlinks RewriteEn

php中實現頁面的幾種方式

腳本 timeout location clas replace asc idt lee 實現 親測,not復制粘貼 PHP中實現頁面跳轉有一下幾種方式,看了幾個人寫的不是很條理,自己整理一下 在PHP腳本代碼中實現 <?php header("locati

.Net語言 APP開發平臺——Smobiler學習日誌:在手機應用開發中如何實現地圖

demo hand 操作 窗體 clas com ps1 ati void 一、目標樣式 我們要實現上圖中的效果,需要如下的操作: 二、跳轉地圖代碼 VB: Private Sub Button1_Click(sender As Object, e As Ev

自動檢測,pc端與移動端打開網頁時到對應的地址

gen rec useragent androi tex index func hone oca 方法1 <script> if(navigator.platform.indexOf(‘Win32‘)!=-1){ //pc window.location.hre

站點映射到外網踩到的坑,丟失端口

部分 encoding attribute 虛擬 一段 head 將不 clas span 今天準備的線上演示版本,把端口映射到外網後,發現跳轉不正確,丟失了端口。 環境:centos7+docker 方案嘗試: 1、修改docker的端口映射,直接把nginx的端口改為外

thinkphp前臺使用JQuery後臺處理後回調

res 列表 首頁 || logs else foreach 進行 信息 thinkphp前臺使用JQuery跳轉後臺處理後回調記錄。 前臺html <input id="query" type="tel" value="" placeholder="搜索編號查詢"

ios/oc banner廣告位---- 打開瀏覽器鏈接

廣告 open toa ges -- length str ner rec //廣告位 打開瀏覽器跳轉鏈接 -(void)jumpToAdUrl:(UITapGestureRecognizer *)tap{ // self.ad_link_Str = @"http