Activiti(1) - TaskRuntime API 入门
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的源码,注释里已经详细地解释了代码的含义。完整代码请查看[官方源码](https://github.com/Activiti/activiti-examples/tree/master/activiti-api-basic-task-example):
```java
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												
											Activiti(1) - TaskRuntime API 入门的更多相关文章
- Web API 入门指南 - 闲话安全
		
Web API入门指南有些朋友回复问了些安全方面的问题,安全方面可以写的东西实在太多了,这里尽量围绕着Web API的安全性来展开,介绍一些安全的基本概念,常见安全隐患.相关的防御技巧以及Web AP ...
 - 转载-Web API 入门
		
An Introduction to ASP.NET Web API 目前感觉最好的Web API入门教程 HTTP状态码 Web API 强势入门指南 Install Mongodb Getting ...
 - Hadoop MapReduce编程 API入门系列之压缩和计数器(三十)
		
不多说,直接上代码. Hadoop MapReduce编程 API入门系列之小文件合并(二十九) 生成的结果,作为输入源. 代码 package zhouls.bigdata.myMapReduce. ...
 - Web API入门指南(安全)转
		
安全检测的工具站点:https://www.owasp.org/index.php/Category:Vulnerability_Scanning_Tools Web API入门指南有些朋友回复问了些 ...
 - 【ASP.NET Web API教程】1 ASP.NET Web API入门
		
原文 [ASP.NET Web API教程]1 ASP.NET Web API入门 Getting Started with ASP.NET Web API第1章 ASP.NET Web API入门 ...
 - Web API 入门指南
		
Web API 入门指南 - 闲话安全2013-09-21 18:56 by 微软互联网开发支持, 231 阅读, 3 评论, 收藏, 编辑 Web API入门指南有些朋友回复问了些安全方面的问题,安 ...
 - 使用Jax-rs 开发RESTfull API 入门
		
使用Jax-rs 开发RESTfull API 入门 本文使用 Jersey 2开发RESTfull API.Jersey 2 是 JAX-RS 接口的参考实现 使用到的工具 Eclipse Neon ...
 - Web API 入门 二  媒体类型
		
还是拿上面 那篇 Web API 入门 一 的那个来讲 在product类中加一个时间属性
 - HBase编程 API入门系列之create(管理端而言)(8)
		
大家,若是看过我前期的这篇博客的话,则 HBase编程 API入门系列之put(客户端而言)(1) 就知道,在这篇博文里,我是在HBase Shell里创建HBase表的. 这里,我带领大家,学习更高 ...
 
随机推荐
- P1640 [SCOI2010]连续攻击游戏 二分图构造
			
https://www.luogu.org/problemnew/show/P1640 题意 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10 ...
 - RodRego  — a register machine
			
RodRego - a register machine 寄存器机(register machine)是一种类似于图灵机一样的抽象机器,是计算机模型的一种,他和其他的抽象机一样都是图灵等价的. Rod ...
 - np问题(大数阶乘取模)
			
转自 np问题 题目描述: LYK 喜欢研究一些比较困难的问题,比如 np 问题. 这次它又遇到一个棘手的 np 问题.问题是这个样子的:有两个数 n 和 p,求 n 的阶乘对 p 取模后的结果. L ...
 - 章节十六、8-ITestResult接口
			
一.ITestResult:该接口就像一个监听器,能够监听每个方法执行后的状态(是否成功)并将结果返回给我们. package testclasses1; import org.testng.anno ...
 - Elasticsearch之联想词示例
			
public class LianXiangWord { private static RestClient client; static { client=RestClient.builder(ne ...
 - Mybatis系列(一)入门
			
Mybatis系列(一)入门 mybatis简介 MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结 ...
 - linux中安装vsftpd出现的问题
			
提示:安装vsftpd必须要在root用户下才能安装成功,进入root:su -(中间有空格) 问题: 1.再用命令getsebool -a | grep ftpd命令查看查看状态时出现的问题:SEL ...
 - App 冷启动与热启动及启动白屏优化
			
介绍一下 app 冷启动和热启动方式来实现 app 秒开的效果.那么,先来看看什么叫冷启动和热启动. 冷启动:指 app 被后台杀死后,在这个状态打开 app,这种启动方式叫做冷启动. 热启动:指 a ...
 - Corosync fence盘替换
			
前面创建盘的步骤省略 1.在节点A执行: sbd -d /dev/mapper/fence_lun001 -d /dev/mapper/fence_lun002 -d /dev/mapper/fenc ...
 - kubernetes部署高可用Harbor
			
前言 本文Harbor高可用依照Harbor官网部署,主要思路如下,大家可以根据具体情况选择搭建. 部署Postgresql高可用集群.(本文选用Stolon进行管理,请查看文章<kuberne ...