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 入门的更多相关文章

  1. Web API 入门指南 - 闲话安全

    Web API入门指南有些朋友回复问了些安全方面的问题,安全方面可以写的东西实在太多了,这里尽量围绕着Web API的安全性来展开,介绍一些安全的基本概念,常见安全隐患.相关的防御技巧以及Web AP ...

  2. 转载-Web API 入门

    An Introduction to ASP.NET Web API 目前感觉最好的Web API入门教程 HTTP状态码 Web API 强势入门指南 Install Mongodb Getting ...

  3. Hadoop MapReduce编程 API入门系列之压缩和计数器(三十)

    不多说,直接上代码. Hadoop MapReduce编程 API入门系列之小文件合并(二十九) 生成的结果,作为输入源. 代码 package zhouls.bigdata.myMapReduce. ...

  4. Web API入门指南(安全)转

    安全检测的工具站点:https://www.owasp.org/index.php/Category:Vulnerability_Scanning_Tools Web API入门指南有些朋友回复问了些 ...

  5. 【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入门 ...

  6. Web API 入门指南

    Web API 入门指南 - 闲话安全2013-09-21 18:56 by 微软互联网开发支持, 231 阅读, 3 评论, 收藏, 编辑 Web API入门指南有些朋友回复问了些安全方面的问题,安 ...

  7. 使用Jax-rs 开发RESTfull API 入门

    使用Jax-rs 开发RESTfull API 入门 本文使用 Jersey 2开发RESTfull API.Jersey 2 是 JAX-RS 接口的参考实现 使用到的工具 Eclipse Neon ...

  8. Web API 入门 二 媒体类型

    还是拿上面 那篇 Web API 入门 一  的那个来讲 在product类中加一个时间属性

  9. HBase编程 API入门系列之create(管理端而言)(8)

    大家,若是看过我前期的这篇博客的话,则 HBase编程 API入门系列之put(客户端而言)(1) 就知道,在这篇博文里,我是在HBase Shell里创建HBase表的. 这里,我带领大家,学习更高 ...

随机推荐

  1. 重识 ArrayList

    前言 ArrayList 作为 Java 集合框架中最常用的类,在一般情况下,用它存储集合数据最适合不过.知其然知其所以然,为了能更好地认识和使用 ArrayList,本文将从下面几方面深入理解 Ar ...

  2. GitExtensions使用教程

    GitExtensions工具使用教程 第一步:安装 1.双击:GitExtensions24703SetupComplete.msi <ignore_js_op> image001.pn ...

  3. 传入值参数&传入引用参数的区别

    传值&传引用 1.传值 是把实参的值赋值给行参 那么对行参的修改,不会影响实参的值 2.传地址 是传值的一种特殊方式,只是他传递的是地址 那么传地址以后,实参和行参都指向同一个对象 3.传引用 ...

  4. CF Edu54 E. Vasya and a Tree DFS+树状数组

    Vasya and a Tree 题意: 给定一棵树,对树有3e5的操作,每次操作为,把树上某个节点的不超过d的子节点都加上值x; 思路: 多开一个vector记录每个点上的操作.dfs这颗树,同时以 ...

  5. HDU2874 Connections between cities 最近公共祖先

    第一次按常规的方法求,将所有的查询的u,v,和最近公共祖先都保存起来,然后用tarjan+并查集求最近公共祖先.因为询问的次数过多,所以在保存查询的时候总是MLE,后来参考了一下别人的代码,才突然觉悟 ...

  6. Codeforces 935 C Fifa and Fafa

    935 C 题意:Fifa想用wifi下载足球游戏, 但是Fafa是个流浪狂魔, 所以Fifa想让他的wifi在公寓里尽量覆盖最大的面积,并且不覆盖到Fafa和公寓外的人,fafa的坐标可以在公寓外. ...

  7. Python 基础 3 - 元组

    元组与列表区别 Python 元组与列表类似,不同之处在于列表可以修改,元组不可以修改 元组用小括号 () 定义,列表用方括号 [] 定义 元组不可修改,列表可修改 元组创建 只需要在小括号 () 内 ...

  8. Linux下Mysql启动异常排查方案

    遇到Mysql启动异常问题,可以从以下几个方面依次进行问题排查: (1)如果遇到“Can't connect to local MySQL server through socket '/tmp/my ...

  9. pytho的traceback的解读

    写 Python 代码的时候,当代码中出现错误,会在输出的时候打印 Traceback  错误信息,很多初学者看到那一堆错误信息,往往都会处于懵逼状态,脑中总会冒出一句,这都是些啥玩意.如果你是第一次 ...

  10. 警告:stream not available

    1.修改mybatis.org//DTD Config 3.0//EN更改为mybatis.org//DTD//EN 2.将url换成http://mybatis.org/dtd/mybatis-3- ...