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. spring-cloud-kubernetes与k8s的configmap

    本文是<spring-cloud-kubernetes实战系列>的第六篇,主要内容是在kubernetes上部署一个java web应用,该应用使用了spring-cloud-kubern ...

  2. P1251 餐巾计划问题 费用流

    https://www.luogu.org/problemnew/show/P1251 题意 有一家酒店,酒店每天需要ri张桌布,桌布可以现买,p元.可以通过快洗店,等m天,f元.可以通过慢洗店,等n ...

  3. 2018年全国多校算法寒假训练营练习比赛(第五场)H Tree Recovery

    Tree Recovery 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言262144K 64bit IO Format: %lld 链接:https://w ...

  4. codeforces 749D Leaving Auction(二分)

    题目链接:http://codeforces.com/problemset/problem/749/D 题意:就是类似竞拍,然后报价肯定要比上一个高,然后查询输入k个数表示那些人的竞拍无效, 输出最后 ...

  5. yzoj1657货仓选址 题解

    题面: 在一条数轴上有N家商店,它们的坐标分别为 A[1]~A[N].现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品.为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的 ...

  6. ASP.NET MVC实现依赖注入

    在java的spring中有自动注入功能,使得代码变得更加简洁灵活,所以想把这个功能移植到c#中,接下来逐步分析实现过程 1.使用自动注入场景分析 在asp.net mvc中,无论是什么代码逻辑分层, ...

  7. Day002_LInux基础_常用命令

    #空格和tab键↓↓mkdir 创建目录 ↓ls list 显示目录里面的内容详情↓cd change directory 切换目录,进入到目录↓pwd 显示当前所在路径 ,定位↓###绝对路径和相对 ...

  8. Docker搭建disconf环境,三部曲之三:细说搭建过程

    Docker下的disconf实战全文链接 <Docker搭建disconf环境,三部曲之一:极速搭建disconf>: <Docker搭建disconf环境,三部曲之二:本地快速构 ...

  9. git bash 界面修改成linux界面

    在使用git bash操作git时,$符总是另起一行,给人感觉特别不爽,特别想修改成linux下一样的风格. 在git输入命令: vim ~/.bash_profile 进入insert模式,添加内容 ...

  10. FreeSql (三十三)CodeFirst 类型映射

    前面有介绍过几篇 CodeFirst 内容文章,有 <(二)自动迁移实体>(https://www.cnblogs.com/FreeSql/p/11531301.html) <(三) ...