Activiti 快速入門指南(Activiti Core)

Activiti Core

新API的目的很明確,以知足下列需求:java

  • 隔離內部和外部API以提供向後兼容
  • 經過遵循單責任方法爲模塊化提供將來的途徑
  • 減小之前版本的API的混亂狀況
  • 歸入安全和身份管理
  • 對於但願依賴流行框架提供的約定的常見用例,能夠減小實現的時間
  • 供基礎服務的替代實現

還沒有棄用舊的API,所以仍然能夠自由使用它,可是強烈建議使用新的API以得到長期支持。git

該API處於Beta測試階段,這意味着可能會在GA發佈以前對其進行更改和完善。github

TaskRuntime API

若是要構建業務應用程序,那麼爲組織中的用戶和組建立任務可能會很方便。web

TaskRuntime API在這裏能夠爲你提供幫助。spring

能夠從GitHub克隆此示例:https://github.com/Activiti/activiti-examples數據庫

該部分的代碼能夠在「activiti-api-basic-task-example」 maven模塊中找到。api

若是你在Spring Boot 2應用程序中運行,則只需添加activiti-spring-boot-starter依賴項和一個數據庫驅動程序,便可將H2用於內存中存儲。數組

https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/pom.xml#L45安全

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
</dependency>

建議使用BOM。app

https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/pom.xml#L30

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.activiti.dependencies</groupId>
            <artifactId>activiti-dependencies</artifactId>
            <version>7.1.0.M5</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencyManagement>
注意:可使用如下連接檢索最新版本: https://search.maven.org/search?q=activiti-dependencies

如今,切換到DemoApplication.classhttps://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/src/main/java/org/activiti/examples/DemoApplication.java#L25

而後,你將可使用TaskRuntime

@Autowired
private TaskRuntime taskRuntime;

將bean注入應用程序後,你應該可以建立任務並與任務交互。

public interface TaskRuntime {
  TaskRuntimeConfiguration configuration();
  Task task(String taskId);
  Page tasks(Pageable pageable);
  Page tasks(Pageable pageable, GetTasksPayload payload);
  Task create(CreateTaskPayload payload);
  Task claim(ClaimTaskPayload payload);
  Task release(ReleaseTaskPayload payload);
  Task complete(CompleteTaskPayload payload);
  Task update(UpdateTaskPayload payload);
  Task delete(DeleteTaskPayload payload);
  ...
}

例如,你能夠經過執行如下操做來建立任務:

https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/src/main/java/org/activiti/examples/DemoApplication.java#L45

taskRuntime.create(
            TaskPayloadBuilder.create()
                .withName("First Team Task")
                .withDescription("This is something really important")
                .withGroup("activitiTeam")
                .withPriority(10)
           .build());

只有屬於activitiTeam的用戶和全部者(當前登陸的用戶)才能看到此任務。

你可能已經注意到,可使用TaskPayloadBuilder以流暢的方式參數化將要發送到TaskRuntime的信息。

爲了處理安全性、角色和組,依賴於Spring Security模塊。由於在Spring Boot應用程序內部,因此可使用UserDetailsS​​ervice來配置可用用戶及其各自的組和角色,目前在@Configuration類中執行此操做:

https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/src/main/java/org/activiti/examples/DemoApplicationConfiguration.java#L26

這裏須要注意的重要一點是,爲了做爲用戶與TaskRuntime API進行交互,你須要擁有角色:ACTIVITI_USER(授予的權限:ROLEACTIVITIUSER)。

與REST端點進行交互時,受權機制將設置當前登陸的用戶,可是爲了這個例子,使用了一個工具類(https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/src/main/java/org/activiti/examples/SecurityUtil.java#L26),容許在上下文中設置手動選擇的用戶。請注意,除非你正在嘗試而且想要在不通過REST端點的狀況下更改用戶,不然切勿這樣作。查看「web」示例,以查看根本不須要該實用工具類的更多真實場景​​。

該示例中要強調的最後一件事是任務事件偵聽器的註冊:

https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/src/main/java/org/activiti/examples/DemoApplication.java#L89

@Bean
public TaskRuntimeEventListener taskAssignedListener() {
  return taskAssigned
           -> logger.info(
                 ">>> Task Assigned: '"
                + taskAssigned.getEntity().getName()
                +"' We can send a notification to the assignee: "
                + taskAssigned.getEntity().getAssignee());
}

你能夠根據須要註冊任意多個TaskRuntimeEventListener,當服務觸發運行時事件時,這將使你的應用程序獲得通知。

ProcessRuntime API

以相似的方式,若是要開始使用ProcessRuntime API,則須要包含與以前相同的依賴項,目標是在未來提供更大的靈活性和單獨的運行時,可是目前,相同的Spring Boot Starter同時提供TaskRuntimeProcessRuntime API。

該部分的代碼能夠在「activiti-api-basic-process-example」 maven模塊內找到。

public interface ProcessRuntime {
  ProcessRuntimeConfiguration configuration();
  ProcessDefinition processDefinition(String processDefinitionId);
  Page processDefinitions(Pageable pageable);
  Page processDefinitions(Pageable pageable,
              GetProcessDefinitionsPayload payload);
  ProcessInstance start(StartProcessPayload payload);
  Page processInstances(Pageable pageable);
  Page processInstances(Pageable pageable,
              GetProcessInstancesPayload payload);
  ProcessInstance processInstance(String processInstanceId);
  ProcessInstance suspend(SuspendProcessPayload payload);
  ProcessInstance resume(ResumeProcessPayload payload);
  ProcessInstance delete(DeleteProcessPayload payload);
  void signal(SignalPayload payload);
  ...
}

TaskRuntime API類似,爲了與ProcessRuntime API進行交互,當前登陸的用戶必須具備「ACTIVITI_USER」角色。

首先,注入ProcessRuntime

https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-process-example/src/main/java/org/activiti/examples/DemoApplication.java#L32

@Autowired
private ProcessRuntime processRuntime;

@Autowired
private SecurityUtil securityUtil;

和以前同樣,咱們須要SecurityUtil幫助器來定義與API交互的用戶。

如今,能夠開始與ProcessRuntime進行交互了:

https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-process-example/src/main/java/org/activiti/examples/DemoApplication.java#L47

Page processDefinitionPage = processRuntime
                                .processDefinitions(Pageable.of(0, 10));
logger.info("> Available Process definitions: " +
                  processDefinitionPage.getTotalItems());
for (ProcessDefinition pd : processDefinitionPage.getContent()) {
  logger.info("\t > Process definition: " + pd);
}

流程定義須要放在/src/main/resources/processes/中,在此示例中,定義瞭如下流程:

使用Spring Scheduling功能來每秒啓動一個流程,從數組中拾取隨機值以進行處理:

https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-process-example/src/main/java/org/activiti/examples/DemoApplication.java#L67

@Scheduled(initialDelay = 1000, fixedDelay = 1000)
public void processText() {
  securityUtil.logInAs("system");
  String content = pickRandomString();
  SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yy HH:mm:ss");
  logger.info("> Processing content: " + content
                    + " at " + formatter.format(new Date()));
  ProcessInstance processInstance = processRuntime
                  .start(ProcessPayloadBuilder
                       .start()
                       .withProcessDefinitionKey("categorizeProcess")
                       .withProcessInstanceName("Processing Content: " + content)
                       .withVariable("content", content)
                       .build());
  logger.info(">>> Created Process Instance: " + processInstance);
}

與以前同樣,使用ProcessPayloadBuilder以流暢的方式參數化咱們但願啓動哪一個流程,以及使用哪一個流程變量。

如今,若是咱們回顧一下流程定義,你將發現3個服務任務,爲了提供這些服務任務的實現,你須要定義Connector

https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-process-example/src/main/java/org/activiti/examples/DemoApplication.java#L81

@Bean
public Connector processTextConnector() {
  return integrationContext -> {
      Map inBoundVariables = integrationContext.getInBoundVariables();
      String contentToProcess = (String) inBoundVariables.get("content")
     // Logic Here to decide if content is approved or not
     if (contentToProcess.contains("activiti")) {
        logger.info("> Approving content: " + contentToProcess);
        integrationContext.addOutBoundVariable("approved",true);
     } else {
        logger.info("> Discarding content: " + contentToProcess);
        integrationContext.addOutBoundVariable("approved",false);
     }
    return integrationContext;
  };
}

這些鏈接器使用Bean名稱(在此示例中爲「processTextConnector」)自動鏈接到ProcessRuntime,此bean名稱是從流程定義內的serviceTask元素的implementation屬性中選取的:

https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-process-example/src/main/resources/processes/categorize-content.bpmn20.xml#L22

<bpmn:serviceTask id="Task_1ylvdew" name="Process Content" implementation="processTextConnector">

這個新的Connector接口是JavaDelegate的天然演變,新版本的Activiti Core將經過將它們包裝在Connector實現中來嘗試重用JavaDelagate

public interface Connector {
  IntegrationContext execute(IntegrationContext integrationContext);
}

鏈接器接收帶有流程變量的IntegrationContext,並返回修改後的IntegrationContext,其結果須要映射回流程變量。

在前面的示例中,鏈接器實現正在接收「content」變量,並基於內容處理邏輯添加「approved」變量。

在這些鏈接器內,你可能會包含系統到系統的調用,例如REST調用和基於消息的交互。

查看Maven模塊activiti-api-spring-integration-example以獲取更高級的示例,該示例使用Spring Integrations基於文件輪詢器啓動流程。

完整示例

你能夠找到使用ProcessRuntimeTaskRuntime API來自動執行如下流程的示例:

該部分的代碼能夠在「activiti-api-basic-full-example」 maven模塊內找到。

做爲僅ProcessRuntime的示例,它還對一些輸入內容進行了分類,可是在這種狀況下,該過程依賴於人工來決定是否批准內容。與以前同樣,有一個調度任務,該任務每5秒建立一個新的流程實例,而且模擬用戶檢查是否有可用的任務要處理。

https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-full-example/src/main/java/org/activiti/examples/DemoApplication.java#L63

https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-full-example/src/main/java/org/activiti/examples/DemoApplication.java#L85

UserTask建立給一個potentialOwner,在本示例中爲「activitiTeam」組,可是在這種狀況下,咱們不會像第一個示例那樣手動建立任務,每次啓動流程時,流程實例都會爲咱們建立任務。

https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-full-example/src/main/resources/processes/categorize-human-content.bpmn20.xml#L38

<bpmn:userTask id="Task_1ylvdew" name="Process Content">
  <bpmn:incoming>SequenceFlow_09xowo4</bpmn:incoming>
  <bpmn:outgoing>SequenceFlow_1jzbgkj</bpmn:outgoing>
  <bpmn:potentialOwner>
    <bpmn:resourceAssignmentExpression>
      <bpmn:formalExpression>activitiTeam</bpmn:formalExpression>
    </bpmn:resourceAssignmentExpression>
  </bpmn:potentialOwner>
</bpmn:userTask>

屬於該組的用戶將能夠領取任務並處理任務。

相關文章
相關標籤/搜索