activiti学习笔记(十七)官方文档阅读

2018-07-15  本文已影响246人  云师兄

之前学习activiti时买过《activiti实战》,感觉这本书有些关键的细节并没有讲到,于是找了activiti的官方文档,想照着官方的英文文档系统学习一下activiti。本次分享的就是照着官方文档在spring boot环境下集成。

首先添加maven依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>activiti</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter-basic</artifactId>
            <version>6.0.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>6.0.6</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.M9</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

接着在resouces目录下新建一个processes目录,这个目录下放置流程文件one-task-process.bpmn20.xml,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<definitions
        xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
        xmlns:activiti="http://activiti.org/bpmn"
        targetNamespace="Examples">

    <process id="oneTaskProcess" name="The One Task Process">
        <startEvent id="theStart" />
        <sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" />
        <userTask id="theTask" name="my task" />
        <sequenceFlow id="flow2" sourceRef="theTask" targetRef="theEnd" />
        <endEvent id="theEnd" />
    </process>

</definitions>

添加后,我们可以加一个配置类,在应用启动后打印流程相关信息:

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Bean
    public CommandLineRunner init(final RepositoryService repositoryService,
                                  final RuntimeService runtimeService,
                                  final TaskService taskService) {

        return new CommandLineRunner() {
            @Override
            public void run(String... strings) throws Exception {
                System.out.println("Number of process definitions : "
                        + repositoryService.createProcessDefinitionQuery().count());
                System.out.println("Number of tasks : " + taskService.createTaskQuery().count());
                runtimeService.startProcessInstanceByKey("oneTaskProcess");
                System.out.println("Number of tasks after process start: " + taskService.createTaskQuery().count());
            }
        };
    }
}

启动应用后,结果如下:

Number of process definitions : 1
Number of tasks : 1
Number of tasks after process start: 1

可以看出已经自动找到流程文件,所以流程定义为1,启动后就创建了一个任务,说明环境搭建成功,接下来我们就可以继续学习activiti的相关概念了。

ProcessEngine

流程引擎(ProcessEngine)类是activiti进行流程相关api调用的中心点,通过ProcessEngine可以各种service类,结构如下:


屏幕快照 2018-07-15 上午11.40.50.png

流程引擎通过配置生成,而在spring boot 中引入activiti的依赖包后就可以自动生成流程引擎了。
流程引擎可以获取到的service有:

RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
ManagementService managementService = processEngine.getManagementService();
IdentityService identityService = processEngine.getIdentityService();
HistoryService historyService = processEngine.getHistoryService();
FormService formService = processEngine.getFormService();
DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();

RepositoryService

这个类的功能涉及到下面几个方面:

TaskService

TaskService则是围绕着任务task相关的操作,任务是由有权限的处理人来执行的。借助TaskService可以实现的功能有:

IdentityService

IdentityService这个类则是用于对用户和组的管理。

FormService

FormService这个类不是必须的。它主要操作关于start form和task form两个观点。官网解释为:A start form is a form that is shown to the user before the process instance is started, while a task form is the form that is displayed when a user wants to complete a form.

HistoryService

HistoryService这个类则是拥有查询流程流转过程中保存的历史数据,从数据中可以得知每个节点的具体操作信息。
下面是一个获取历史数据例子:

HistoryService historyService = processEngine.getHistoryService();
HistoricProcessInstance historicProcessInstance =
historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult();
System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());

ManagementService和DynamicBpmnService

这两个类不常用到,这里就不再阐述了。

异常策略

activiti异常类的基类是org.activiti.engine.ActivitiException,这个异常类有几个子类,用于应对不同的异常,如果有某个异常被这几个子类范围内,就会归为ActivitiExceptions异常抛出。

启动流程实例

基于部署后生成的某个流程定义,我们可以启动多个流程实例。流程运行时的各种状态可以通过RuntimeService类来查询。在创建流程实例的时候,可以给特定的流程实例设置流程变量process variables,这也是不同流程实例的不同之处。创建流程实例有很多种方法,下面使用了RuntimeService类来创建,并且在启动的时候还添加了需要的流程参数。

Map<String, Object> variables = new HashMap<String, Object>();
variables.put("employeeName", "Kermit");
variables.put("numberOfDays", new Integer(4));
variables.put("vacationMotivation", "I'm really tired!");

RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacationRequest", variables);

// Verify that we started a new process instance
Log.info("Number of process instances: " + runtimeService.createProcessInstanceQuery().count());

完成任务

流程中的用户组和用户有一个自己需要处理的任务列表,他可以通过下面这种方法查询:

TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
for (Task task : tasks) {
  Log.info("Task available: " + task.getName());
}

获取到指定的任务后,我们可以使用TaskService类的complete方法完成任务:

Task task = tasks.get(0);

Map<String, Object> taskVariables = new HashMap<String, Object>();
taskVariables.put("vacationApproved", "false");
taskVariables.put("managerMotivation", "We have a tight deadline!");
taskService.complete(task.getId(), taskVariables);

暂挂和激活流程

我们可以将部署好的流程定义进行暂挂操作,使用的类是RepositoryService。流程定义被赞挂后就不能再创建流程实例了,只有重新激活以后才能再次正常创建流程实例。
下面是暂挂后再次创建流程跑出异常的例子:

repositoryService.suspendProcessDefinitionByKey("vacationRequest");
try {
  runtimeService.startProcessInstanceByKey("vacationRequest");
} catch (ActivitiException e) {
  e.printStackTrace();
}

激活流程定义的方法为:repositoryService.activateProcessDefinitionXXX。
此外,流程实例也支持暂挂和激活,使用的方法为:

runtimeService.suspendProcessInstance();
runtimeService.activateProcessInstance();

查询流程信息

有两种查询流程引擎中的信息的方法:query API 和 native queries。前者是使用activiti提供的固定格式的查询方法,如下:

List<Task> tasks = taskService.createTaskQuery()
    .taskAssignee("kermit")
    .processVariableValueEquals("orderId", "0815")
    .orderByDueDate().asc()
    .list();

由于这种查询方法封装了查询格式,对于复杂的sql查询并不支持,为此复杂查询需要用到native queries,即自己写sql语句进行查询:

List<Task> tasks = taskService.createNativeTaskQuery()
  .sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T WHERE T.NAME_ = #{taskName}")
  .parameter("taskName", "gonzoTask")
  .list();

变量

流程实例 process instance,执行对象execution 和 任务 task这三者都有各自作用范围的变量。这些变量存储在 ACT_RU_VARIABLE 表中。

ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, Object> variables);
void setVariable(String executionId, String variableName, Object value);
void setVariableLocal(String executionId, String variableName, Object value);
void setVariables(String executionId, Map<String, ? extends Object> variables);
void setVariablesLocal(String executionId, Map<String, ? extends Object> variables);
Map<String, Object> getVariables(String executionId);
Map<String, Object> getVariablesLocal(String executionId);
Map<String, Object> getVariables(String executionId, Collection<String> variableNames);
Map<String, Object> getVariablesLocal(String executionId, Collection<String> variableNames);
Object getVariable(String executionId, String variableName);
<T> T getVariable(String executionId, String variableName, Class<T> variableClass);
execution.getVariables();
execution.getVariables(Collection<String> variableNames);
execution.getVariable(String variableName);

execution.setVariables(Map<String, object> variables);
execution.setVariable(String variableName, Object value);

transient variable 局部变量

表达式

表达式有两种类型:value-expression 和 method-expression 。前者最终转化为值,如{xxx},后者转化为带参数或者不带参数的方法,如果不带参数,记得带上括号,以便和值表达式区分开,如{func()}

Spring 集成

ProcessEngineFactoryBean

在Spring 框架中使用activiti 引擎从ProcessEngineFactoryBean这个bean开始。这个bean实现了流程引擎的配置和创建。
spring的配置文件内容如下:

<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
    ...
</bean>

<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
  <property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>

现在ProcessEngineFactoryBean配置类已经改为org.activiti.spring.SpringProcessEngineConfiguration这个类了。

事务 Transactions

流程部署

在流程部署的时候,工作流会给流程定义版本号+1;对同一个流程文件多次部署,流程定义的版本号就会从当前版本号最大值加1后更新。启动流程实例的时候,就会使用版本号最大的流程定义去发起流程。

流程图 process diagram

BPMN2.0 介绍

一个简单的流程文件如下:

<definitions
  xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
  xmlns:activiti="http://activiti.org/bpmn"
  targetNamespace="Examples">

  <process id="myProcess" name="My First Process">
    ..
  </process>

</definitions>

根元素为definitions,其下可定义多个流程,为便于维护,一般定义一个流程。
process标签中的id元素就是我们使用runtimeService启动流程实例的时候指定的参数key:

ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess");

而process标签中的name属性则不是必须的,只是显示看的。

参考文档
http://www.mossle.com/docs/activiti/index.html

上一篇下一篇

猜你喜欢

热点阅读