Activiti中的流程歷史保存流程發起人的方法

Activiti中的流程歷史保存流程發起人的方法

源自:http://my.oschina.net/liyuj/blog/380777


摘要 Activiti中流程的活動歷史信息保存在ACT_HI_ACTINST表中,流程歷史信息保存在ACT_HI_PROCINST表中,我們可以通過API或者直接寫SQL進行查詢,但是這裏面並沒有流程發起人的信息,流程發起人信息有的時候還是非常必要的,本文將提供一種方式,保存流程發起人信息,這樣我們就能夠查詢到某人發起的流程了。

        Activiti中流程的歷史信息保存在ACT_HI_ACTINST表中,流程歷史信息保存在ACT_HI_PROCINST表中,我們可以通過API或者直接寫SQL進行查詢,但是這裏面並沒有流程發起人的信息,流程發起人信息有的時候還是非常必要的,比如查詢某人發起的流程或者做相關的統計等。

        鑑於ACT_HI_ACTINST中保存了流程的活動歷史信息,我們還是想在這個表上做文章,但是這個表中並沒有發起人等相關的字段,這時候,我們發現,當一個流程剛發起時,ACT_TYPE_爲startEvent,這時ASSIGNEE_爲空,如果我們能借用這個字段,保存申請人,查詢起來代碼還是比較優雅的,雖然這個字段本身的含義不是申請人。

        另外,ACT_HI_PROCINST表中還有一個START_USER_ID_字段,但是默認爲空。通過上述兩種保存流程發起人的方式,在不同的場景中都能夠通過簡單的方式查詢到流程的發起人信息。

        下一步,就是研究Activiti的代碼了,看看能不能找到相應的擴展點,解決這個問題。

        經過研究,找到了擴展點,開發起來還是比較方便的,下面進行詳細描述,注意,本文的開發基於Activiti5.15.1版本,大體掃了下代碼,更新的5.17版本應該也兼容,但未經過測試。

        對於流程發起時保存ACT_HI_ACTINST表和ACT_HI_PROCINST表的代碼,在DefaultHistoryManager類的recordProcessInstanceStart方法中,所以我們只要想辦法繼承這個類,然後覆寫這個方法即可,而DefaultHistoryManager的創建,是在DefaultHistoryManagerSessionFactory中,而DefaultHistoryManagerSessionFactory的初始化,是在ProcessEngineConfigurationImpl中的initSessionFactories方法,找到這裏,思路已經非常清晰了,需要寫的代碼沒有多少。

        另外,還需要注意一點,Activiti中有一個線程局部變量,保存着線程上下文有關的用戶信息,爲Authentication中的authenticatedUserIdThreadLocal,並且該類提供相關的API進行賦值和取值,因此我們需要在流程發起之前設置該局部變量。

        一、擴展ProcessEngineConfigurationImpl,如果使用Spring集成的話,繼承SpringProcessEngineConfiguration類,覆寫initSessionFactories方法,在該方法中調用addSessionFactory方法添加新的自定義DefaultHistoryManagerSessionFactory;

        二、擴展DefaultHistoryManagerSessionFactory,覆寫openSession方法,在該方法中創建新的DefaultHistoryManager;

        三、擴展DefaultHistoryManager,覆寫recordProcessInstanceStart方法,在該方法中爲assign字段賦值即可,至於當前的流程發起人獲取方法,可以調用Authentication的API獲取;

    具體代碼如下所示:

?
1
2
3
4
5
6
7
8
9
10
import org.activiti.spring.SpringProcessEngineConfiguration;
 
public class ProcessEngineConfiguration extends SpringProcessEngineConfiguration {
 
    @Override
    protected void initSessionFactories() {
        super.initSessionFactories();
        super.addSessionFactory(new ProcessHistoryManagerSessionFactory());
    }
}

    

?
1
2
3
4
5
6
7
8
9
10
import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.persistence.DefaultHistoryManagerSessionFactory;
 
public class ProcessHistoryManagerSessionFactory extends DefaultHistoryManagerSessionFactory {
 
    @Override
    public Session openSession() {
        return new ProcessHistoryManager();
    }
}

    

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class ProcessHistoryManager extends DefaultHistoryManager {
    @Override
    public void recordProcessInstanceStart(ExecutionEntity processInstance) {
        if(isHistoryLevelAtLeast(HistoryLevel.ACTIVITY)) {
          HistoricProcessInstanceEntity historicProcessInstance = new HistoricProcessInstanceEntity(processInstance);
          getDbSqlSession().insert(historicProcessInstance);
       
          IdGenerator idGenerator = Context.getProcessEngineConfiguration().getIdGenerator();
           
          String processDefinitionId = processInstance.getProcessDefinitionId();
          String processInstanceId = processInstance.getProcessInstanceId();
          String executionId = processInstance.getId();
       
          HistoricActivityInstanceEntity historicActivityInstance = new HistoricActivityInstanceEntity();
          historicActivityInstance.setId(idGenerator.getNextId());
          historicActivityInstance.setProcessDefinitionId(processDefinitionId);
          historicActivityInstance.setProcessInstanceId(processInstanceId);
          historicActivityInstance.setExecutionId(executionId);
          historicActivityInstance.setActivityId(processInstance.getActivityId());
          historicActivityInstance.setActivityName((String) processInstance.getActivity().getProperty("name"));
          historicActivityInstance.setActivityType((String) processInstance.getActivity().getProperty("type"));
          Date now = Context.getProcessEngineConfiguration().getClock().getCurrentTime();
          historicActivityInstance.setStartTime(now);
           
          if (processInstance.getTenantId() != null) {
              historicActivityInstance.setTenantId(processInstance.getTenantId());
          }
          //通過Authentication.getAuthenticatedUserId()獲取當前線程綁定的用戶ID。
          historicActivityInstance.setAssignee(Authentication.getAuthenticatedUserId());
           
          getDbSqlSession().insert(historicActivityInstance);
        }      
    }
}

    Activiti在HistoricProcessInstanceEntity的構造器中已經通過Authentication獲取了線程綁定用戶ID。因此,我們只需要在調用runtimeService的startProcessInstance的相關方法之前賦值即可,賦值方法有兩種:

?
1
2
identityService.setAuthenticatedUserId();//調用官方的開放API;
Authentication.setAuthenticatedUserId();//直接調用底層實現;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章