天天看點

Activiti原理分析(三)使用者管理

Activiti 自帶一套使用者管理系統,維護了使用者和使用者組的對應關系,通過

identityService

可以對它們進行增删改查。當你在

UserTask

中指定了使用者組時,Activiti 就會使用它維護的這個關系尋找使用者了。

但是這也為 Activiti 的使用帶來了困難,因為一般應用都有一套自建的使用者管理,不可能去使用 Activiti 這一套,就不得不花一些成本來對接,而且對接方法都比較 hack,個人覺得這是 Activiti 設計得不太好的地方。

受理人與候選人

一個

UserTask

可以設定一個受理人(Assignee),或者多個候選人。

受理人就是負責完成該任務的人,在審批場景下就可以了解成審批人,隻能有一個,如果要有多個的話則應該使用

上一篇文章

提到的多執行個體任務。

<!--kermit就是受理人的 id-->
<userTask id="theTask" name="my task" activiti:assignee="kermit" />      

候選人可以有一個或者多個,他們都是受理人的“候選”,他們要“搶”任務,誰先調用了

taskService.claim(taskId, userId);

,誰就變成了任務的受理人。

<!--兩個候選人 kermit與gonzo-->
<userTask id="theTask" name="my task" activiti:candidateUsers="kermit,gonzo"/>      
<!--management使用者組的所有使用者作為候選人-->
<userTask id="theTask" name="my task" activiti:candidateGroups="management"/>      

内置的使用者管理

Activiti 中的使用者模型非常簡單,就是使用者和使用者組之間的多對多關系,是以隻涉及三張表:

  • ACT_ID_USER

    :使用者資訊
  • ACT_ID_GROUP

    :使用者組資訊
  • ACT_ID_MEMBERSHIP

    :存儲使用者和使用者組之間的多對多關聯
Activiti原理分析(三)使用者管理

流程運作時使用者資訊

在應用中一般會調用下面的方法查詢某個使用者的 task:

// 查詢所有候選 userId 的任務
            List<Task> tasks = taskService.createTaskQuery()
                    .taskCandidateUser(userId).list();
            // 查詢所有 userId 受理的任務
            List<Task> tasks = taskService.createTaskQuery()
                    .taskAssignee(userId).list();
            // 查詢所有 userId候選或者受理的任務
            List<Task> tasks = taskService.createTaskQuery()
                    .taskCandidateOrAssigned(userId).list();      

受理人查詢

ACT_RU_TASK

表中本來就有一個

ASSIGNEE_

字段表示受理人,所有當你使用

taskAssignee(userId)

查詢時,直接就是用的

ASSIGNEE_=userId

ACT_RU_TASK

表中去查的。

候選人查詢

在流程運作時還會有一張

ACT_RU_IDENTITYLINK

表,用來記錄流程運作時相關的人員資訊,比如流程發起人,參與人,Task 的候選人等資訊:

Activiti原理分析(三)使用者管理

其中

TYPE_

有以下幾種取值:

  • starter: 流程發起人
  • participant: 流程參與人,目前的受理人就會被記錄在這裡
  • candidate: Task 對應的候選人或者候選使用者組

因為這是一張運作時表,是以裡面資料是會随着流程運轉不斷增删改的。

當你使用

taskCandidateUser(userId)

條件查詢時其實就是去這張表裡根據

TYPE_='candidate' AND USER_ID_=userId

找到使用者候選的 Task

候選使用者組

假如你将 UserTask 配置成

activiti:candidateGroups="management"

,如果 userId 屬于

manangement

使用者組,那麼使用

taskCandidateUser(userId)

條件查詢,也是能查出該 UserTask 的。

此時就需要用到上一小節提到的使用者管理相關表了。Activiti 如果會去

ACT_ID_MEMBERSHIP

中找到該使用者的 groupId,然後去

ACT_RU_IDENTITYLINK

中根據

GROUP_ID_

查。

Activiti 如何與已有使用者管理系統對接?

從上面的分析可以看到,Activiti 隻有在你配置了

candidateGroups

才可能去查詢内置的使用者管理資訊,是以個人建議是就不要使用

candidateGroups

配置了,全部使用

candidateUsers

assignee

,然後在 userId 裡加入一些特征區分使用者組或者别的業務相關的東西,比如加個字首

GROUP-groupId

,之後就全部用自己業務系統裡的 id 去查 Task。不用擔心這些ID在 Activiti 内置的使用者管理系統中沒有,Activiti 根本不會去校驗這個。

當然也有人研究過一些更加麻煩的對接方法,列出如下,也可以參考:

    • 往 Activiti 内置的使用者表中,同步自己業務的使用者資料。個人感覺比較麻煩,而且也容易出各種問題
    • 将 Activiti 使用者相關存儲類用自己的實作類換掉。聽起來很複雜,但是因為 Activiti 6 所采用的可插拔的存儲層設計,其實隻要替換兩類就可以了,後面我有空會再研究一下它的存儲層設計。而且如果要搞分庫分表的話,存儲層本來就是要重新弄的,順手就可以把使用者管理換掉。
    • 用業務使用者資料的視圖替換掉 Activiti 内置使用者管理的這三張表。感覺不一定所有的業務使用者資料都可以映射到 Activiti 的使用者模型,所有通用性有限

參考