Activiti7工作流學習筆記二 流程實例

Activiti7工作流學習筆記二 流程實例

參與者(可以是用戶也可以是程序)按照流程定義內容發起一個流程,這就是一個流程實例。是動態的。

流程定義和流程實例的圖解:

在這裏插入圖片描述

流程定義部署在 activiti 後,就可以在系統中通過 activiti 去管理該流程的執行,執行流程表示流程的一次執行。

比如部署系統請假流程後,如果某用戶要申請請假這時就需要執行這個流程,如果另外一個用戶也要申請請假則也需要執行該流程,每個執行互不影響,每個執行是單獨的流程實例。

業務系統與Activiti整合原理

在這裏插入圖片描述

  • 業務系統存儲具體的請假信息
  • activiti中存儲流程相關的信息,並記錄業務標識(businesskey
    啓動流程實例時,指定的businesskey,就會在act_ru_execution (流程實例的執行表,當前流程進行的狀態,一條記錄)中存儲businesskey

Businesskey:業務標識,通常爲業務表的主鍵,業務標識和流程實例一一對應。業務標識來源於業務系統。存儲業務標識就是根據業務標識來關聯查詢業務系統的數據。

比如:請假流程啓動一個流程實例,就可以將請假單的 id 作爲業務標識存儲到 activiti 中,將來查詢activiti 的流程實例信息就可以獲取請假單的 id 從而關聯查詢業務系統數據庫得到請假單信息。

啓動流程實例,添加businessKey

/**
 * com.lxf.activiti.ProcessDefinition
 *  啓動流程實例,添加進businessKey
 *
 *  本質:act_ru_execution表中的businessKey的字段要存入業務標識
 * @author lxf
 * @version 1.0
 * @date 2020/4/25 20:18
 */
public class BusinessKeyAdd {

  public static void main(String[] args) {
    //1.得到ProcessEngine對象
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    //2.得到RuntimeService對象
    RuntimeService runtimeService = processEngine.getRuntimeService();

    //3.啓動流程實例,同時還要指定業務標識businessKey  它本身就是請假單的id
    //第一個參數:是指流程定義key
    //第二個參數:業務標識businessKey
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday", "1001");

    //4.輸出processInstance相關的屬性,取出businessKey使用:processInstance.getBusinessKey()
    System.out.println(processInstance.getBusinessKey());

  }
}

掛起、激活流程實例

某些情況可能由於流程變更需要將當前運行的流程暫停而不是直接刪除,流程暫停後將不會繼續執
行。
在這裏插入圖片描述
操作流程定義爲掛起狀態,該流程定義下邊所有的流程實例全部暫停:
流程定義爲掛起狀態該流程定義將不允許啓動新的流程實例,同時該流程定義下所有的流程實例將全部掛起暫停執行。

  /**
   * 全部流程實例掛起
   */
  public void suspendOrActivateAllProcessDefinition(){
    //1.得到ProcessEngine對象
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    //2.得到RepositoryService
    RepositoryService repositoryService = processEngine.getRepositoryService();

    //3.查詢流程定義的對象
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
        .processDefinitionKey("holiday").singleResult();

    //4.得到當前流程定義的實例是否都爲暫停狀態
    boolean suspended = processDefinition.isSuspended();

    String processDefinitionId = processDefinition.getId();
    //5.判斷
    if(suspended){
      //說明是暫停,就可以激活操作
      repositoryService.activateProcessDefinitionById(processDefinitionId,true
          ,null);
      System.out.println("流程定義:"+processDefinitionId+"激活");
    }else{
      repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
      System.out.println("流程定義:"+processDefinitionId+"掛起");
    }
  }

操作流程實例對象,針對單個流程執行掛起操作,某個流程實例掛起則此流程不再繼續執行,完成該流程實例的當前任務將報異常。

/**
   * 單個流程實例掛起
   */
  public void suspendOrActiveSingleProcessInstance(){

    //1.得到ProcessEngine對象
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    //2.得到RuntimeService
    RuntimeService runtimeService = processEngine.getRuntimeService();

    //3.查詢流程實例對象
    ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
        .processInstanceId("2501").singleResult();

    //4.得到當前流程定義的實例是否都爲暫停狀態
    boolean suspended = processInstance.isSuspended();

    String processInstanceId = processInstance.getId();
    //5.判斷
    if(suspended){
      //說明是暫停,就可以激活操作
      runtimeService.activateProcessInstanceById(processInstanceId);
      System.out.println("流程:"+processInstanceId+"激活");
    }else{
      runtimeService.suspendProcessInstanceById(processInstanceId);
      System.out.println("流程定義:"+processInstanceId+"掛起");
    }
  }

個人任務

分配任務負責人

固定分配

在進行業務流程建模時指定固定的任務負責人
在這裏插入圖片描述
properties 視圖中,填寫 Assignee項爲任務負責人。

由於固定分配方式,任務只管一步一步執行任務,執行到每一個任務將按照 bpmn 的配置去分配任務負責人。

表達式分配

UEL 表達式:Activiti使用 UEL表達式,UELjava EE6 規範的一部分,UELUnified Expression Language)即統一表達式語言,activiti支持兩個 UEL表達式:UEL-valueUEL-method

  • UEL-value 定義如下:
    在這裏插入圖片描述
    assignee 這個變量是 activiti的一個流程變量。
    或:
    在這裏插入圖片描述
    user 也是 activiti的一個流程變量,user.assignee表示通過調用 usergetter方法獲取值。

  • UEL-method方式如下:
    在這裏插入圖片描述
    userBeanspring 容器中的一個 bean,表示調用該 beangetUserId()方法。

  • UEL-methodUEL-value結合
    再比如:
    ${ldapService.findManagerForEmployee(emp)},ldapServicespring 容器的一個 beanfindManagerForEmployee 是該 bean 的一個方法,empactiviti流程變量,emp 作爲參數傳到 ldapService.findManagerForEmployee 方法中。

  • 其它
    表達式支持解析基礎類型、bean、list、arraymap,也可作爲條件判斷。
    如下:${order.price > 100 && order.price < 250}

使用流程變量分配任務

  1. 定義任務分配流程變量
    在這裏插入圖片描述
  2. 設置流程變量
    在啓動流程實例時設置流程變量,如下:
//啓動流程實例時設計流程變量
//定義流程變量
Map<String, Object> variables = new HashMap<String, Object>();
//設置流程變量assignee
variables.put("assignee", "張三");
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey(processDefinitionKey, variables);

由於使用了表達式分配,必須保證在任務執行過程表達式執行成功,比如:
某個任務使用了表達式${order.price > 100 && order.price < 250},當執行該任務時必須保證order 在流程變量中存在,否則activiti 異常.

動態設置assignee

/**
 * com.lxf.activiti.processInstance
 * 啓動流程實例,動態設置assignee
 * @author lxf
 * @version 1.0
 * @date 2020/4/26 7:54
 */
public class AssigneeUEL {

  public static void main(String[] args) {
    //1.得到ProcessEngine對象
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    //2.得到RuntimeService對象
    RuntimeService runtimeService = processEngine.getRuntimeService();

    //3.設置assignee的取值   用戶可以在界面上設置流程的執行人
    //key的值與流程定義中的UEL表達式對應
    Map<String,Object> map = new HashMap<>();
    map.put("assignee0","zhangsan");
    map.put("assignee1","lishi");
    map.put("assignee2","wangwu");

    //4.啓動流程實例,同時還要設置流程定義的assignee的值
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday2", map);

    //5.輸出
    System.out.println(processEngine.getName());
  }
}

監聽器分配

任務監聽器是發生對應的任務相關事件時執行自定義 java 邏輯 或表達式。
任務相當事件包括:
在這裏插入圖片描述

  • Create:任務創建後觸發
  • Assignment:任務分配後觸發
  • Delete:任務完成後觸發
  • All:所有事件發生都觸發
    java 邏輯 或表達式:
    表達式參考上邊的介紹的 UEL 表達式,這裏主要介紹監聽類使用。
    定義任務監聽類,且類必須實現 org.activiti.engine.delegate.TaskListener 接口
public class MyTaskListener implements TaskListener {
	@Override
	public void notify(DelegateTask delegateTask) {
		//這裏指定任務負責人
		delegateTask.setAssignee("張三");
	} 
}

使用監聽器分配方式,按照監聽事件去執行監聽類的notify 方法,方法如果不能正常執行也會影響任務的執行。

在這裏插入圖片描述
Class類需要指定到實現 org.activiti.engine.delegate.TaskListener 的具體類上,但一般使用較少,使用UEL表達式較多

查詢任務

查詢任務負責人的待辦任務:

// 查詢當前個人待執行的任務
@Test
public void findPersonalTaskList() {
	// 流程定義key
	String processDefinitionKey = "holiday";
	// 任務負責人
	String assignee = "張三丰";
	// 創建TaskService
	TaskService taskService = processEngine.getTaskService();
	List<Task> list = taskService.createTaskQuery()//
	.processDefinitionKey(processDefinitionKey)//
	.includeProcessVariables().taskAssignee(assignee).list();
	for (Task task : list) {
		System.out.println("----------------------------");
		System.out.println("流程實例id:" + task.getProcessInstanceId());
		System.out.println("任務id:" + task.getId());
		System.out.println("任務負責人:" + task.getAssignee());
		System.out.println("任務名稱:" + task.getName());
	} 
}

關聯 businessKey

activiti實際應用時,查詢待辦任務可能要顯示出業務系統的一些相關信息.
比如:查詢待審批請假單任務列表需要將請假單的日期、請假天數等信息顯示出來,請假天數等信息在業務系統中存在,而並沒有在 activiti數據庫中存在,所以是無法通過 activitiapi查詢到請假天數等信息。

實現:
在查詢待辦任務時,通過businessKey(業務標識 )關聯查詢業務系統的請假單表,查詢出請假天數等信息。
在這裏插入圖片描述

辦理任務

指定任務 id,調用 TaskService完成任務:

// 完成任務
@Test
public void completTask() {
	//任務id
	String taskId = "10305";
	// 創建TaskService
	TaskService taskService = processEngine.getTaskService();
	Task task = taskService.createTaskQuery().taskId(taskId)
			   .taskAssignee(assignee).singleResult();
	if(task != null){
		taskService.complete(taskId);
		System.out.println("完成任務");
	}	
}

注意:在實際應用中,完成任務前需要校驗任務的負責人是否具有該任務的辦理權限

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