Activiti(1) – TaskRuntime API 入門

  • 2019 年 10 月 5 日
  • 筆記

Activiti 是一個自動化工作流框架。它能幫助企業快速搭建分散式、高擴展的工作流框架。
下面這篇文章將會帶你探索Activiti 工作流核心運行時API – TaskRuntime API。(P.S. 這篇文章基本上是我對官網文章的翻譯,英文好的請看官網原文

TaskRuntime API

下面有寫一些demo.這些demo是Activiti官網展示的一些例子,你可以從這個地址下載這些demo。
TaskRunTime API 部分的例子可以在activiti-api-basic-task-example模組中找到。

pom.xml

在Spring Boot2 中使用Activiti添加相關依賴以及資料庫驅動就行。
比如在pom.xml文件中添加以下依賴:pom.xml

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

建議使用下面的BOM

<dependencyManagement>      <dependencies>          <dependency>              <groupId>org.activiti</groupId>              <artifactId>activiti-dependencies</artifactId>              <version>7.1.0.M4</version>              <scope>import</scope>              <type>pom</type>          </dependency>      </dependencies>  </dependencyManagement>

註冊TaskRuntime實例

通過下面的方式我們可以將TaskRuntime的實例註冊到APP中。

@Autowired  private TaskRuntime taskRuntime;

TaskRuntime介面中定義了一系列方法來幫助我們創建任務實例以及與任務進行交互,源碼如下所示。

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);    ...  }

我們可以使用TaskPayloadBuilder參數化任務的資訊,來平滑地構建一個TaskRuntime實例:

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

上面方式創建的任務只能被 「activitiTeam」 這個分組以及任務擁有者(當前登錄用戶)看到。

角色與分組

在SpringBoot 工程中,為了安全考慮,角色和分組的創建Activiti依賴Spring Security 模組。在SpringBoot 工程中我們可以使用 UserDetailsService來配置可以與任務進行交互的用戶以及他們各自對應的角色和分組。這個demo中是在@Configuration 配置的類中進行設置的.

需要注意的是:與TaskRuntime API 交互,必須擁有 ACTIVITI_USER 角色 (許可權是: ROLE_ACTIVITI_USER)。

當與REST端點進行交互的時候,Activiti授權機構將自動設置當前登錄用戶。但是因為這個demo是一個教學性質的實例,它允許我們手動設置當前登錄用戶。在實際的工作場景中,千萬不要這麼做,除非你想不經過REST端點(例如HTTP請求)就改變登錄用戶。

任務事件監聽器

最後一件需要強調的事情就是任務事件監聽器的註冊。
我們可以按照需要註冊任意多個TaskRuntimeEventListeners。當服務觸發運行時事件時,監聽器能夠監聽到這一動作,並通知應用程式。

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


DemoApplication 源碼

下面是DemoApplication的源碼,注釋里已經詳細地解釋了程式碼的含義。完整程式碼請查看官方源碼

package org.activiti.examples;    import org.activiti.api.runtime.shared.query.Page;  import org.activiti.api.runtime.shared.query.Pageable;  import org.activiti.api.task.model.Task;  import org.activiti.api.task.model.builders.TaskPayloadBuilder;  import org.activiti.api.task.runtime.TaskRuntime;  import org.activiti.api.task.runtime.events.TaskAssignedEvent;  import org.activiti.api.task.runtime.events.TaskCompletedEvent;  import org.activiti.api.task.runtime.events.listener.TaskRuntimeEventListener;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.boot.CommandLineRunner;  import org.springframework.boot.SpringApplication;  import org.springframework.boot.autoconfigure.SpringBootApplication;  import org.springframework.context.annotation.Bean;    @SpringBootApplication  public class DemoApplication implements CommandLineRunner {        private Logger logger = LoggerFactory.getLogger(DemoApplication.class);        @Autowired      private TaskRuntime taskRuntime;      @Autowired      private SecurityUtil securityUtil;        public static void main(String[] args) {          SpringApplication.run(DemoApplication.class, args);        }        @Override      public void run(String... args) {            // Using Security Util to simulate a logged in user          securityUtil.logInAs("salaboy");            // Let's create a Group Task (not assigned, all the members of the group can claim it)          //  Here 'salaboy' is the owner of the created task          logger.info("> Creating a Group Task for 'activitiTeam'");          taskRuntime.create(TaskPayloadBuilder.create()                  .withName("First Team Task")                  .withDescription("This is something really important")                  .withCandidateGroup("activitiTeam")                  .withPriority(10)                  .build());            // Let's log in as 'other' user that doesn't belong to the 'activitiTeam' group          securityUtil.logInAs("other");            // Let's get all my tasks (as 'other' user)          logger.info("> Getting all the tasks");          Page<Task> tasks = taskRuntime.tasks(Pageable.of(0, 10));            // No tasks are returned          logger.info(">  Other cannot see the task: " + tasks.getTotalItems());            // Now let's switch to a user that belongs to the activitiTeam          securityUtil.logInAs("erdemedeiros");            // Let's get 'erdemedeiros' tasks          logger.info("> Getting all the tasks");          tasks = taskRuntime.tasks(Pageable.of(0, 10));            // 'erdemedeiros' can see and claim the task          logger.info(">  erdemedeiros can see the task: " + tasks.getTotalItems());            String availableTaskId = tasks.getContent().get(0).getId();            // Let's claim the task, after the claim, nobody else can see the task and 'erdemedeiros' becomes the assignee          logger.info("> Claiming the task");          taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(availableTaskId).build());            // Let's complete the task          logger.info("> Completing the task");          taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(availableTaskId).build());      }        @Bean      public TaskRuntimeEventListener<TaskAssignedEvent> taskAssignedListener() {          return taskAssigned -> logger.info(">>> Task Assigned: '"                  + taskAssigned.getEntity().getName() +                  "' We can send a notification to the assginee: " + taskAssigned.getEntity().getAssignee());      }      @Bean      public TaskRuntimeEventListener<TaskCompletedEvent> taskCompletedListener() {          return taskCompleted -> logger.info(">>> Task Completed: '"                  + taskCompleted.getEntity().getName() +                  "' We can send a notification to the owner: " + taskCompleted.getEntity().getOwner());      }  }

下面是運行結果


2019-10-05 16:58:53.900 INFO 6268 — [ main] o.a.e.DemoApplicationConfiguration : > Registering new user: salaboy with the following Authorities[[ROLE_ACTIVITI_USER, GROUP_activitiTeam]]
2019-10-05 16:58:54.175 INFO 6268 — [ main] o.a.e.DemoApplicationConfiguration : > Registering new user: ryandawsonuk with the following Authorities[[ROLE_ACTIVITI_USER, GROUP_activitiTeam]]
2019-10-05 16:58:54.422 INFO 6268 — [ main] o.a.e.DemoApplicationConfiguration : > Registering new user: erdemedeiros with the following Authorities[[ROLE_ACTIVITI_USER, GROUP_activitiTeam]]
2019-10-05 16:58:54.580 INFO 6268 — [ main] o.a.e.DemoApplicationConfiguration : > Registering new user: other with the following Authorities[[ROLE_ACTIVITI_USER, GROUP_otherTeam]]
2019-10-05 16:58:54.742 INFO 6268 — [ main] o.a.e.DemoApplicationConfiguration : > Registering new user: admin with the following Authorities[[ROLE_ACTIVITI_ADMIN]]

2019-10-05 16:59:00.232 INFO 6268 — [ main] org.activiti.examples.SecurityUtil : > Logged in as: salaboy
2019-10-05 16:59:00.233 INFO 6268 — [ main] org.activiti.examples.DemoApplication : > Creating a Group Task for ‘activitiTeam’
2019-10-05 16:59:00.261 INFO 6268 — [ main] org.activiti.examples.SecurityUtil : > Logged in as: other
2019-10-05 16:59:00.261 INFO 6268 — [ main] org.activiti.examples.DemoApplication : > Getting all the tasks
2019-10-05 16:59:00.380 INFO 6268 — [ main] org.activiti.examples.DemoApplication : > Other cannot see the task: 0
2019-10-05 16:59:00.380 INFO 6268 — [ main] org.activiti.examples.SecurityUtil : > Logged in as: erdemedeiros
2019-10-05 16:59:00.380 INFO 6268 — [ main] org.activiti.examples.DemoApplication : > Getting all the tasks
2019-10-05 16:59:00.395 INFO 6268 — [ main] org.activiti.examples.DemoApplication : > erdemedeiros can see the task: 1
2019-10-05 16:59:00.395 INFO 6268 — [ main] org.activiti.examples.DemoApplication : > Claiming the task
2019-10-05 16:59:00.405 INFO 6268 — [ main] org.activiti.examples.DemoApplication : >>> Task Assigned: ‘First Team Task’ We can send a notification to the assginee: erdemedeiros
2019-10-05 16:59:00.425 INFO 6268 — [ main] org.activiti.examples.DemoApplication : > Completing the task
2019-10-05 16:59:00.457 INFO 6268 — [ main] org.activiti.examples.DemoApplication : >>> Task Completed: ‘First Team Task’ We can send a notification to the owner: salaboy