1. 程式人生 > >springboot2.0整合工作流activiti6.0,以及與業務整合時的一些坑

springboot2.0整合工作流activiti6.0,以及與業務整合時的一些坑

1、首先,要在springboot工程的pom檔案中引入相關jar包

<dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-spring</artifactId>
      <version>6.0.0</version>
</dependency>

2、新增配置檔案,注入activiti的service

@Configuration
public class ActivitiConfiguration {

    @Autowired
    private DataSource dataSource;
    @Autowired
    private PlatformTransactionManager platformTransactionManager;

	@Bean
	public SpringProcessEngineConfiguration springProcessEngineConfiguration(){
		SpringProcessEngineConfiguration spec = new SpringProcessEngineConfiguration();
        spec.setDataSource(dataSource);
        spec.setTransactionManager(platformTransactionManager);
		spec.setDatabaseSchemaUpdate("true");
		Resource[] resources = null;
        // 啟動自動部署流程
		try {
			resources = new PathMatchingResourcePatternResolver().getResources("classpath*:bpmn/*.bpmn");
		} catch (IOException e) {
			e.printStackTrace();
		}
		spec.setDeploymentResources(resources);
		return spec;
	}
	
	@Bean
	public ProcessEngineFactoryBean processEngine(){
		ProcessEngineFactoryBean processEngineFactoryBean = new ProcessEngineFactoryBean();
		processEngineFactoryBean.setProcessEngineConfiguration(springProcessEngineConfiguration());
		return processEngineFactoryBean;
	}

	
	@Bean
	public RepositoryService repositoryService() throws Exception{
		return processEngine().getObject().getRepositoryService();
	}
	@Bean
	public RuntimeService runtimeService() throws Exception{
		return processEngine().getObject().getRuntimeService();
	}
	@Bean
	public TaskService taskService() throws Exception{
		return processEngine().getObject().getTaskService();
	}
	@Bean
	public HistoryService historyService() throws Exception{
		return processEngine().getObject().getHistoryService();
	}
	
}

3、與業務進行整合。

      這裡我使用activiti變數儲存流程資訊,在流程執行中使用流程監聽器去修改業務表。為了簡單,業務表和activiti的表在一個數據庫內,這樣就不會涉及分散式事務的問題了,直接使用spring的事務管理器就可以控制事務的提交,回滾了。

    3.1 畫流程圖

     

    3.2設定流程資訊

       

   3.3設定任務監聽器

        這裡有不同的設定方式,我這裡用的是expression,這樣就不用實現activiti的JavaDelegate介面了,而且同一個類中

        可以實現很多方法,就像下面的apply方法就是自定義的一個方法。(Java Class和Delegate expression都需要實現

        接口才行)。

        注意配置中的Event事件,這裡可以選擇監聽器觸發的時機,任務監聽器有craete,assignment,complete,all四

       種。 連線監聽器有take,還有其他監聽器請自行探索。

      

 上面的apply方法中,我們可以看到有兩個引數,其中execution是屬於activiti內建的引數,java程式碼中只需要使用   DelegateExecution接收即可,從中我們可以獲取流程相關的一些資訊,而task是我自定義的一個引數,如果要想在

 監聽器中監聽,我們需要在流程變數中設定名為task的引數,變數分為全域性的流程變數,區域性的任務變數,和瞬時

 變數,因為我這裡 task變數不需要存庫,只是想在監聽器中獲取一下,所以這裡我儲存的是瞬時變數。

 注意點:因為在流程啟動的時候我沒有直接設定臨時變數的地方,所以我是在啟動流程例項的時候觸發了一個監聽器,

                然後在監聽器中設定了的瞬時變數。

4、啟動流程,並執行稽核流程

     4.1 啟動流程

// 這裡的myProcess就是我們上面流程中設定的Id,businessKey是業務key,可以用來和
// 業務進行繫結
runtimeService.startProcessInstanceByKey("myProcess", "businessKey");

    4.2執行稽核流程

// 通過業務key查詢出對應的任務
Task task = taskService.createTaskQuery()
.processInstanceBusinessKey("businessKey").singleResult();
// 將相關資訊放入工作流區域性變數,和任務進行繫結
Map<String, Object> localVariable = new HashMap<>(2);
localVariable.put("user", "username");
localVariable.put("time" ,"2018-12-09");
taskService.setVariablesLocal(task.getId(), localVariable);

// 設定臨時變數
Map<String, Object> variable = new HashMap<>(1);
variable.put("result", "pass");
// 完成任務並設定瞬時變數(這裡還可以通過taskService直接設定瞬時變數)
taskService.complete(task.getId(),null,variable);

   4.3完成任務會觸發我們的任務監聽器(設定event為complete)

    @Transactional(rollbackFor = Exception.class)
    public void apply(DelegateExecution execution,Task task){
        // 這裡可以對我們的業務表進行操作,保證業務表和工作流中的狀態是匹配的
    }

  以上,許可權是在業務表中進行控制的,所以的工作流執行的過程中,我沒有給任務指定任何處理人(工作流不指定

 任務處理人也可以一直往下執行),在我的業務方法中,就相當於一直呼叫next方法,流程就會按照正常流程一直

 往下執行,直到結束。 如果是需要駁回等流程,那就需要單獨處理判斷了。

  如果需要設定處理人,只需要在任務的屬性中進行配置即可,如下圖:

總結:使用工作流有兩種方式

           1、任務處理許可權還是在業務表中進行控制,通過業務key查詢任務並完成任務,工作流只是起一個流轉以及

                儲存流程歷史資訊的作用,對於業務來說,只要通過業務key找到流程任務,然後執行下一步即可,駁回等

                操作需要自己處理判斷,然後完成任務後,自動觸發作流的監聽器去修改業務的具體資料。

           2、任務處理許可權由工作流控制,我們在工作流中指定任務的處理人(處理人可以動態指定),然後通過處理人查

                詢任務並完成任務,然後自動觸發作流的監聽器去修改業務的具體資料。

注意事項:1、如果想要在監聽器中繫結任務變數,需要在任務監聽器中進行設定任務變數,千萬不要在任務之後的連

               線監聽器中設定任務變數,因為在一個事務中,上一個任務屬於還沒有完成,所以還能設定。但是!!!這樣

               設定會導致任務變數儲存到act_ru_variable中,正常應該儲存到act_hi_varinst中。不然設定的時候雖然不會報

               錯,但是到最後結束流程的時候,你就會發現結束不了了,因為外來鍵原因,act_ru_variable中存在任務變數沒有

               刪除,匯出結束任務時,任務資訊不能刪除,然後報錯!!!

                2、瞬時變數的設定問題,啟動流程的時候,沒有直接設定瞬時變數的地方,所以我找到了在啟動時觸發監聽器

               設定。但是,流程如果執行到了最後,後面沒有使用者任務節點了,這時候,就不能設定瞬時變量了,不然activiti

               會轉換型別異常,它會將瞬時變數轉為全域性變數型別,這時就會報錯,轉換異常!!!