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>

属于该组的用户将能够领取任务并处理任务。

相关文章
相关标签/搜索