activiti框架搭建及问题记录

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: activiti框架搭建及问题记录

什么是activiti


activiti是一个业务流程管理的框架,这是一个开源的,首先业务流程管理应用就是BPM(business process management),简单点将就是这玩意儿就是做审批用的,它可以创建审批,以及审批的应用。类似于钉钉这个软件中的OA审批创建一样,创建以后应用过程基本是一致的。


activiti配置


首先activiti是有25张表的,所以对于它的应用个人推荐还是作为一个单独的项目来开发,由这个项目提供服务即可。


首先创建项目配置pom依赖

    <properties>
        <activiti.version>7.0.0.Beta1</activiti.version>
    </properties>
    <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn 模型处理 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-model</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn 转换 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn json数据转换 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn 布局 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-layout</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- activiti 云支持 -->
        <dependency>
            <groupId>org.activiti.cloud</groupId>
            <artifactId>activiti-cloud-services-api</artifactId>
            <version>${activiti.version}</version>
        </dependency>
    <!--数据库连接-->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>


配置文件


基本的配置xml方式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/contex
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!-- 这里可以使用 链接池 dbcp-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/activiti" />
        <property name="username" value="root" />
        <property name="password" value="root" />
        <property name="maxActive" value="3" />
        <property name="maxIdle" value="1" />
    </bean>
    <bean id="processEngineConfiguration"
          class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!-- 引用数据源 上面已经设置好了-->
        <property name="dataSource" ref="dataSource" />
        <!-- activiti数据库表处理策略 -->
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>
</beans>

第二种方式通过java代码进行配置

import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * DruidDataSourceConfiguration
 *数据库配置类
 * @author 15821
 * @date 13:11 2021/12/11
 */
@Configuration
public class DataSourceConfiguration {
    @Bean("dataSource")
    public BasicDataSource getDruidDataSource(
            @Value("${spring.datasource.driver-class-name}")
                    String driverClassName, // 数据库驱动程序
            @Value("${spring.datasource.url}")
                    String url, // 数据库连接地址
            @Value("${spring.datasource.username}")
                    String username, // 数据库的用户名
            @Value("${spring.datasource.password}")
                    String password, // 数据库的用户名
            @Value("${spring.datasource.tomcat.min-idle}")
                    int minIdle, // 最小维持连接数
            @Value("${spring.datasource.tomcat.max-active}")
                    int maxActive // 最大连接数
    ) {
        BasicDataSource dataSource = new BasicDataSource(); // 实例化DataSource子类对象
        dataSource.setDriverClassName(driverClassName); // 数据库驱动程序
        dataSource.setUrl(url); // 数据库的连接地址
        dataSource.setUsername(username); // 数据库用户名
        dataSource.setPassword(password); // 数据库密码
        dataSource.setMinIdle(minIdle); // 最小维持的连接数量
        dataSource.setMaxActive(maxActive); // 最大的连接数量
        return dataSource;
    }
}

对应数据库的配置信息在yml文件种

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/activiti?nullCatalogMeansCurrent=true
    username: root
    password: 123456
    tomcat:
      max-active: 3
      min-idle: 1

activiti的引擎配置

import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.transaction.PlatformTransactionManager;
import java.io.IOException;
/**
 * ActivitiConfiguration
 *activiti的引擎配置
 * @author 15821
 */
@Configuration
public class ActivitiConfiguration {
    @Autowired
    @Qualifier("dataSource")
    private BasicDataSource DataSource;
    @Autowired
    private PlatformTransactionManager platformTransactionManager;
    /**
     * 注册 activiti的配置信息
     */
    @Bean("processEngineConfiguration")
    public SpringProcessEngineConfiguration getProcessEngineConfiguration(){
        SpringProcessEngineConfiguration configuration
                = new SpringProcessEngineConfiguration();
        configuration.setDataSource(DataSource);       // 添加数据源
        configuration.setTransactionManager(platformTransactionManager);    // 添加事务
        configuration.setDatabaseSchemaUpdate("true");  // 如果有表则不创建
        configuration.setDbHistoryUsed(true);   // 允许查看历史信息
        configuration.buildProcessEngine();  //执行创建25张表,如果已经创建就不再创建了
        // 自动部署 bpmn文件
        Resource[] resources = null;
        try {
            resources= new PathMatchingResourcePatternResolver().getResources("classpath*:bpmn/*.bpmn20.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //这里在程序启动时就去扫描了resource包中的资源,然后进行了部署。不需要在单独部署流程。
        configuration.setDeploymentResources(resources);
        return configuration;
    }
    /**
     * 注册 ProcessEngineFactoryBean
     */
    @Bean
    public ProcessEngineFactoryBean processEngine(){
        ProcessEngineFactoryBean factoryBean = new ProcessEngineFactoryBean();
        factoryBean.setProcessEngineConfiguration(getProcessEngineConfiguration());
        return factoryBean;
    }
    /**
     * 注册 RepositoryService
     */
    @Bean
    public RepositoryService repositoryService() throws Exception{
        return processEngine().getObject().getRepositoryService();
    }
    /**
     * 注册 RuntimeService
     */
    @Bean
    public RuntimeService runtimeService() throws Exception{
        return processEngine().getObject().getRuntimeService();
    }
    /**
     * 注册 TaskService
     */
    @Bean
    public TaskService taskService() throws Exception{
        return processEngine().getObject().getTaskService();
    }
    /**
     * 注册 HistoryService
     */
    @Bean
    public HistoryService historyService() throws Exception{
        return processEngine().getObject().getHistoryService();
    }
}

这是两种配置方式,配置完成以后启动程序后activiti会自动创建数据表一共25张。关于这个25张表的功能这里就不赘述了,有需要的可以上网查一下都有说明。

至此我们的程序就启动成功了。


那么审批(流程)怎么创建呢?


可以通过在idea种安装插件创建流程

搜索:Activiti BPMN visualizer,我这里是已经安装好的。

这里使用这个可视化界面可以进行bpm文件的编辑,鼠标右击会出现菜单,根据菜单选择需要的结点。

结点中的信息配置如下:

这里设置的任务处理人这里是设置的变量,方便动态设置后面会讲到这个怎么使用

以上这些就是流程模板的创建了。

下面就是在代码中具体操作了。

首先我们要知道activiti有一个流程引擎,这个引擎可以为我们提供7种服务

RepositoryServer:操作流程定义的方法。

Runtime:操作流程实例的方法。

FormServer:操作流程表单的方法。

TaskServer:操作任务的方法,例如(任务的完成、挂起、激活、添加处理人、认领、删除等操作)

HistoryServer:查询历史流程实例、历史变量、历史任务的方法

IdentityServer:操作用户或者用户组的方法。

ManagementServer:查询数据库表中的数据、表的元数据以及命令等方法。

我这次使用只有这两个加粗标记的服务,其它服务暂时还没有涉及到


流程启动


这个使用的就是Runtime的服务,这是创建流程实例的moudleName,这个参数是你创建的流程种的 这个id值,后面这个variables是一个map<String,Object>,这个map的key放的就是刚才我们设置的任务处理人的这个变量名称"Sponsor"

Object就是具体的参数了。这是流程实例开启时,需要放入的参数。如果你流程不需要动态参数而是已经制定好的参数那么startProcessInstanceByKey()这个方法时可以不传入这个map参数。

ProcessInstance ins = runtimeService.startProcessInstanceByKey(moudleName, variables);

这个流程实例创建成功后返回的这个ProcessInstance 对象中有该实例的id,后续会用。


任务处理


既然这个流程实例创建以后那么对应的流程中设置任务结点也就会产生,每个任务结点都有对应的处理,只有结点执行完毕这个流程实例才会被删除。


每一个结点的执行处理都需要这个taskService。

这里通过使用processInstanceId()根据流程实例id获取当前实例的任务

Task task =   taskService.createTaskQuery()
               .processInstanceId(processInstanceId)
               .singleResult();

获取到当前流程实例的任务以后我们可以根据任务的id对这个任务做一些处理,比如根据id完成当前任务,那么流程会继续向下执行,这个任务点就算结束了。


activiti问题分享


数据库创建问题


在项目初期进行部署的时候需要创建数据表,那么数据库创建好了,但是数据表是由activiti创建的。就是咱们配置的datasource这个配置了“nullCatalogMeansCurrent”

这个配置的作用


nullCatalogMeansCurrent = true: 返回指定库涉及表
nullCatalogMeansCurrent = false: 返回所有库涉及表

创建表的时候会先去数据库的information_schema.TABLES中查找字段为TABLE_NAME是否有activiti相关的表。如果有则不进行创建数据表了。所以如果有用于测试的数据库进行已经有了一些activiti的数据表的话,我们进行正式创建的时候在项目的数据库连接的配置里面要加上 nullCatalogMeansCurrent = true: 返回指定库涉及表 这个配置。防止出现数据表没有创建上但也没有提示创建失败这个情况。


activiti事件监听器没有对象的问题


我们业务中有一个功能,就是让流程中的审批人员动态设置,而这里我想到的是使用监听器来动态的配置每一个流程任务结点的负责人。在这里有一个问题就是在本篇博客的上面设置项目的时候我们使用的那6个服务都交由spring bean容器管理了,所以在自己设置的监听器这个类中使用这些服务对象的时候就也是使用注入的形式。但是并没有生效,而是提示null空指针的问题。后来网上查阅资料以及做实验发现。activiti的监听器调用并没有和spring bean 容器做共享。 而是自己实例化调用的我们的写的监听器。

自己编写监听器要实现activiti的TaskListener 这个接口。

public class TaskListenerForSetttingNextAssigneeImpl implements TaskListener {
    @Override
    public void notify(DelegateTask delegateTask) {
        //activiti中监听类不归Spring管,真正使用的时候实际上是使用 new 对象的方式去使用(在当前监听类上加@Service注解没用)
        //所以我们要自己写一个工具类去获取TaskService 的对象(ActivitiConfiguration 中已经将这个类对象放在了SpringIOC容器中)
        //我们要做的是手动拿出SpringIOC容器中TaskService的对象供我们使用
        TaskService taskService= SpringUtil.getObject(TaskService.class);
        //获取当前执行到的任务节点信息
        //通过taskService 中装入的变量信息(实际上装的是下一个审批人)
        String userId=taskService.getVariable(delegateTask.getId(),"nextUserId").toString();
        //设置当前任务的执行人
        delegateTask.setAssignee(userId);
    }
}

这是监听器的配置。这个是任务结点监听器,还有其它两个监听器。这里没有使用就不做叙述了。而且本人还没有具体去学习,,,嘿嘿

后续这个项目如果继续开发了,博主会继续更新相关的使用方式以及碰到的问题解决方法。

以上内容如果有问题的地方还请指出。
/

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
NoSQL 前端开发 Java
基于springboot的学生成绩在线管理系统(部署文档+数据库表结构文档)。Javaee项目,springboot项目.
基于springboot的学生成绩在线管理系统(部署文档+数据库表结构文档)。Javaee项目,springboot项目.
|
NoSQL Java 关系型数据库
基于springboot的人力资源管理系统(部署文档+数据库表结构文档)。Javaee项目,springboot项目。
基于springboot的人力资源管理系统(部署文档+数据库表结构文档)。Javaee项目,springboot项目。
|
6月前
|
安全 NoSQL Java
SpringBoot集成Activiti5.22在线流程设计器
SpringBoot集成Activiti5.22在线流程设计器
218 0
SpringBoot集成Activiti5.22在线流程设计器
|
6月前
|
前端开发 JavaScript Java
基于Springboot+SpringSecurity+Activiti7实现的工作流系统可方便二次开发(附完整源码)
基于Springboot+SpringSecurity+Activiti7实现的工作流系统可方便二次开发(附完整源码)
206 0
|
SQL Java 关系型数据库
Activiti工作流框架学习笔记(二)之springboot2.0整合工作流Activiti6.0
Activiti工作流框架学习笔记(二)之springboot2.0整合工作流Activiti6.0
202 0
|
XML 监控 安全
Activiti整理
一个完整的工作流生命周期会经过5步,并且迭代循环。 定义:工作流生命周期总是从流程定义开始。这个过程包括收集需求,将其转化成流程定义,也就流程图、相关变量、角色定义。 发布:由开发人员打包各种资源,然后在系统管理中发布流程定义。包括:bpmn.xml、自定义表单、任务监听类等。 执行:具体的流程引擎按照事先定义的流程处理路线以任务驱动的方式执行业务流程。 监控:此阶段是依赖执行阶段。业务人员在办理任务的同时收集每个任务(Task)的结果,然后根据结果做出相应处理。 优化:在此阶段,一个完整的流程已经结束,或许能满足业务需求,或者需要优化。
250 0
Activiti整理
|
XML 应用服务中间件 数据格式
Activiti入门操作
Activiti入门操作
|
存储 Java API
Activiti-如何创建Activiti项目和数据表介绍
Activiti-如何创建Activiti项目和数据表介绍
Activiti-如何创建Activiti项目和数据表介绍
|
Java 数据库连接 API
Activiti-流程操作2
Activiti-流程操作2
Activiti-流程操作2
|
Java API 数据库
Activiti-流程操作
Activiti-流程操作
Activiti-流程操作