activiti框架搭建及问题记录

news2024/11/24 8:33:57

activiti应用

  • 什么是activiti
  • activiti配置
    • 首先创建项目配置pom依赖
    • 配置文件
  • 那么审批(流程)怎么创建呢?
    • 流程启动
    • 任务处理
  • activiti问题分享
    • 数据库创建问题
    • 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);
    }
}

这是监听器的配置。这个是任务结点监听器,还有其它两个监听器。这里没有使用就不做叙述了。而且本人还没有具体去学习,,,嘿嘿
在这里插入图片描述
后续这个项目如果继续开发了,博主会继续更新相关的使用方式以及碰到的问题解决方法。
以上内容如果有问题的地方还请指出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/66510.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode中等题之使括号有效的最少添加

题目 只有满足下面几点之一&#xff0c;括号字符串才是有效的&#xff1a; 它是一个空字符串&#xff0c;或者 它可以被写成 AB &#xff08;A 与 B 连接&#xff09;, 其中 A 和 B 都是有效字符串&#xff0c;或者 它可以被写作 (A)&#xff0c;其中 A 是有效字符串。 给定一…

开发工具系列IDEA:配置注释自动生成

一、类、接口、枚举配置&#xff0c;进入idea后&#xff0c;依次打开 File -> Settings -> Editor -> File and Code Templates -> Files /*** FileName: ${NAME}* Author: ${USER}* Date: ${DATE} ${TIME}* Description: ${DESCRIPTION}* History:* <aut…

中国电信移动物联网发展成果与创新实践 ,干货满满

近日&#xff0c;首届移动物联网大会&#xff08;2022&#xff09;&#xff08;以下简称“大会”&#xff09;在江苏省无锡市举办。本次大会由工信部指导&#xff0c;中国信息通信研究院&#xff08;以下简称“中国信通院”&#xff09;、中国通信学会、无锡市人民政府、人民邮…

产品工作流| 项目评估

一、什么是项目评估 根据已有的公开招标书要求&#xff0c;销售侧拿到招标要求&#xff0c;让研发评估项目。 1、需求满足度评估。 2、需求开发项&#xff0c;以及成本评估。 3、总结项目评估。 二、项目评估流程 材料依据&#xff1a; 1、投标材料。 2、项目评估表&#x…

路由器,集线器,交换机,网桥,光猫有啥区别?

网络分层 网线替代了上面的灰色部分&#xff0c;实现物理层互联。 如果想要两台电脑互联成功&#xff0c;还需要确保每一层所需要的步骤都要做到位&#xff0c;这样数据才能确保正确投送并返回。 从数据链路层到物理层&#xff0c;数据会被转为01比特流。 此时需要把比特流传…

【软件测试】小陈她的测试追梦之路,实习开端到测试第一人......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 小陈&#xff1a;我…

中华黄金·金生态合伙人颁奖典礼在珠海站开幕完美收官!!

11月18-19日在广东珠海举行&#xff0c;近百位合伙人亲临现场&#xff0c;强者能人共聚天下&#xff0c;中华黄金合伙人&#xff0c;强强联手引爆市场&#xff0c;汇聚一堂。 本次活动以“金生态”为主题。CNG金生态是中华黄金集团旗下平台&#xff0c;运用WEB3.0核心技术聚合了…

Flink CDC入门实践--基于 Flink CDC 构建 MySQL 和 Postgres 的 Streaming ETL

文章目录前言1.环境准备2.准备数据2.1 MySQL2.2 postgres3.启动flink和flink sql client3.1启动flink3.2启动flink SQL client4.在flink SQL CLI中使用flink DDL创建表4.1开启checkpoint4.2对于数据库中的表 products, orders, shipments&#xff0c; 使用 Flink SQL CLI 创建对…

iOS开发之iOS15.6之后拉流LFLiveKit,画面模糊及16.1马赛克问题

更新了iOS15.6系统后&#xff0c;发现拉取LFLiveKit进行直播的流&#xff0c;竟然是这样的&#xff1a; 模糊不清&#xff0c;于是思考是什么原因导致的。 1、是不是拉流端出现的问题&#xff1f; 使用安卓拉取iOS的直播流&#xff0c;是同样的效果&#xff0c;又考虑到两端使…

【DL】Windows 10系统下安装TensorRT教程

Windows 10系统下安装TensorRT教程(手把手教程): Windows 10系统下安装TensorRT教程: 1.下载 https://developer.nvidia.com/nvidia-tensorrt-download EA 版本代表抢先体验(在正式发布之前)。 GA 代表通用性。表示稳定版,经过全面测试。 TensorRT、cuda、cudnn各版本…

与目前主流的消费返利平台对比,共享购模式有什么优势呢?

大家好&#xff0c;我是林工&#xff0c;之前几期内容都有介绍过共享购的商业模式&#xff0c;同时大家应该都对消费返利这方面有所了解。今天给大家分享一下整套模式的优劣势。 什么是消费返利&#xff1f;消费返利是互联网常见的一个商业模式&#xff0c;是指互联网平台将自…

毕业设计 基于STM32与wifi的天气预报网时钟系统 - 物联网 单片机

文章目录0 前言1 设计内容2 软件设计3 关键代码4 最后0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长自己做的项目系统达不…

为社区成员提供的全新在线分析仪表板(Analytics Dashboard)!

开发者们大家好&#xff01; 我们非常激动地与您分享我们为每个社区成员提供的在线分析仪表板(Online Analytics Dashboard)这一全新的强大功能&#x1f525; 从现在开始&#xff0c;您可以看到您自己的当周、月和所有时间的详细统计数据&#xff0c;包括&#xff1a; 浏览量&a…

The Sandbox Alpha 第三季排行榜公布

排行榜名单已经揭晓&#xff0c;祝贺所有玩家&#xff01; Alpha 第三季已于 11 月 1 日落下帷幕&#xff0c;这是我们目前最大的一季活动&#xff0c;也是展示社区和合作伙伴在过去一年中所创造的诸多体验的机会。 这次也是我们测试新的「边玩边赚」机制的机会&#xff0c;其中…

Vue响应式系统的作用与实现(二)

响应式系统的作用与实现&#xff08;二&#xff09; 这章主要是介绍非原始值的响应式方案。 1.理解Proxy和Reflect&#xff1a; Vue3的响应式数据是基于Proxy实现的&#xff0c;那么我们非常有必要了解Proxy和Refelct。 参考资料&#xff1a;阮一峰的 官方参考资料 简单来…

Python Flask框架 入门详解与进阶

Python Flask框架 入门详解与进阶1.Flask框架 入门2.环境搭建2.1.安装flask1.创建虚拟环境2.激活虚拟环境3.安装flask2.2.flask程序编写1.创建test.py文件2.启动运行2.3.参数说明1.Flask对象的初始化参数第一种 &#xff1a;从配置对象中加载 app.config.from_object(DefaultCo…

chrome108 版本跨域问题

前言 近期&#xff0c;chrome又更新了&#xff0c;自动更新到了chrome的108.0.5359.95&#xff08;正式版本&#xff09; &#xff08;64 位&#xff09;&#xff0c;更新到这个版本后&#xff0c;公司业务收到了一个故障&#xff0c;下面我们就来看看。背景&#xff1a; 客户…

Python——requests模块详解

1、模块说明 requests是使用Apache2 licensed 许可证的HTTP库。 用python编写。 比urllib2模块更简洁。 Request支持HTTP连接保持和连接池&#xff0c;支持使用cookie保持会话&#xff0c;支持文件上传&#xff0c;支持自动响应内容的编码&#xff0c;支持国际化的URL和POS…

公众号查题系统

公众号查题系统 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#xff08;点击跳转…

Unity计算着色器 02

序 在百度了一下显卡以后&#xff0c;总结的话就是这个图。 这个图再总结的话就是左下角的那个框子&#xff0c;一个任务可以分为若干个线程组&#xff0c;每个线程组包含若干个线程。 两个若干&#xff0c;可以看成是两个变量&#xff0c;而且是有关系的——它俩乘积是一个…