美文网首页
activiti学习笔记(十七)官方文档阅读

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

作者: 云师兄 | 来源:发表于2018-07-15 11:20 被阅读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

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

    • RepositoryService是首先会使用到的service,它提供了管理和操作deployments和process definitions的方法。其中process definition是一个bpmn2.0流程的java副本,它表示了流程每一步的行为和结构。deployment是流程引擎进行打包的单元,它包含了流程的xml文件和其他相关资源。当创建一个xml格式的流程文件后,我们将其部署后,就会在数据库生成一份流程定义,部署后的流程就可以被启动了。
    • RepositoryService类基于流程定义启动流程实例 process instance。
    • RepositoryService类可以进行保存和获取流程变量 process variables,流程变量保存的是某个具体流程实例在流程流转时需要的变量。
    • RepositoryService可以查询流程实例和执行对象execution。关于流程实例和执行对象的区别可以自行百度,一般来说在没有分支的情况下,获取到的流程实例和执行对象的内容是一样的,而在有分支的情况下,获取到的流程实例和执行对象是有区别的。
    • 暂挂和激活流程定义,这部分内容将在后面描述。

    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 表中。

    • 流程实例添加变量,在RuntimeService类中启动流程实例时添加
    ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, Object> variables);
    
    • execution中添加变量,RuntimeService类中设置:
    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);
    
    • TaskService获取变量
    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获取变量
    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

    相关文章

      网友评论

          本文标题:activiti学习笔记(十七)官方文档阅读

          本文链接:https://www.haomeiwen.com/subject/ocfppftx.html