Ruoyi框架集成Activiti工作流

一、准备工作:

①创建新的模块 ruoyi-activiti
②在 ruoyi-activiti 中加入依赖
 <dependencies>
        <!-- Activiti -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>7.1.0.M6</version>
        </dependency>
        <dependency>
            <groupId>org.activiti.dependencies</groupId>
            <artifactId>activiti-dependencies</artifactId>
            <version>7.1.0.M6</version>
            <type>pom</type>
        </dependency>

        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-framework</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-system</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-common</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>
    </dependencies>
③在最外层的 pom 文件中引入 ruoyi-activiti 模块
            <!-- actviti-->
            <dependency>
                <groupId>com.ruoyi</groupId>
                <artifactId>ruoyi-activiti</artifactId>
                <version>${ruoyi.version}</version>
            </dependency>
④在 ruoyi-admin 的 pom 文件中引入 ruoyi-activiti 模块:
        <!-- activiti-->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-activiti</artifactId>
        </dependency>
⑤修改 application.yml 文件,添加如下配置
spring:
  activiti:
    #1.flase:默认值。activiti在启动时,对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常
    #2.true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建
    #3.create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)
    #4.drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)
    database-schema-update: true
    #检测历史表是否存在 activiti7默认没有开启数据库历史记录 启动数据库历史记录
    db-history-used: true
    #记录历史等级 可配置的历史级别有none, activity, audit, full
    #none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。
    #activity:级别高于none,保存流程实例与流程行为,其他数据不保存。
    #audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。
    #full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。
    history-level: full
    #校验流程文件,默认校验resources下的processes文件夹里的流程文件
    check-process-definitions: false
  main:
    allow-bean-definition-overriding: true

需要注意的是 application-druid.yml中,主库数据源需添加:&nullCatalogMeansCurrent=true,否则启动可能会出现错误,如下:

# 数据源配置
spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        druid:
            # 主库数据源
            master:
                url: jdbc:mysql://localhost:3306/ruoyi-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
                username: root
                password: 1234
⑥:注意事项

        因为没有写前端页面逻辑,使用 postman 测试前需要在 SecurityConfig 类中添加自定义的访问路径可以被匿名访问,如:.antMatchers("/activiti/**").permitAll()。

二、功能实现:

①:绘制流程

        需要我们先绘制好工作流程,如果希望使用idea进行绘制,可以下载如下插件(Activiti BPMN visualizer 这个插件适用于较高版本的idea,大概是2019以上,如果是以前的版本可以去下载 actBPM ),不过个人觉得这两个插件都并不太好用,可以去 eclipse 中去进行流程绘制,随后再将绘制好的文件粘贴至 idea 中。

 

 不过在 eclipse 中使用 Activiti 工作流也需要添加相应插件,创建的可以先创建任意 java 工程,然后在 New 的时候选择 Other,安装插件之后就可以看到 Activiti 的包选项,选择 Activiti Diagram 创建 bpmn 文件。

 绘制流程时,可以使用鼠标点击右侧的选项,放置在左侧的绘制区,常用的有 Start event ,User task,End event,Gateway。点击空白处可以设置流程的 id :myProcess(这个是默认的,可以自行定义,流程启动时用到的 key 就是这里定义的 id) ,Name: 自定义内容。

 点击 User task 框,可以设置 id,name(当前任务结点的名称) ,之后可以再 Main config 中设置 Assignee(任务负责人),此处可以直接填写指定的用户名如:zhangsan,或者使用表达式 :${assignee} ,后面在程序中给表达式赋值。

 绘图之后还需要勾选一个对应的 Activiti 设置,勾选后当我们保存完 bpmn 文件,会自动生成png图片,到此基础的流程就绘制完成了,只需要将两个文件粘贴到idea。

 

 ②:部署流程

此处使用的是文件上传形式进行的部署,定义一个类,注入 RepositoryService 对象,获取文件名及文件后缀名(因为上传的文件可能是 zip 格式),然后调用相应方法进行部署。

    @Autowired
    private RepositoryService repositoryService;
    
    @Override
    public void depolymentFile(MultipartFile file) throws IOException {
        String filename = file.getOriginalFilename();
        // 获取文件后缀名
        String extension = FilenameUtils.getExtension(filename);
        InputStream fileInputStream = file.getInputStream();
        // 区分是zip部署还是单文件部署
        if(extension.equals("zip")){
            ZipInputStream zipInputStream = new ZipInputStream(fileInputStream);
            repositoryService.createDeployment()
                    .addZipInputStream(zipInputStream)
                    .deploy();
            zipInputStream.close();
        }else {
            repositoryService.createDeployment()
                    .addInputStream(filename,fileInputStream)
                    .deploy();
        }
        fileInputStream.close();
    }
③:启动流程
@Autowired
private RuntimeService runtimeService;

// 定义 map 给表达式赋值
Map<String,Object> map = new HashMap<>();

map.put("assignee0",zhangsan);

map.put("assignee1",lisi);

runtimeService.startProcessInstanceByKey("你的流程定义key",map);
④:申请人提交申请
@Autowired
private TaskService taskService;

// 这里的任务id可以根据部署后得到的 processInstanced对象 以及负责人去获取
Task task = taskService,createTaskQuery()
    .processInstanceId(processInstance.getId)
    .taskAssignee("负责人")
    // 此处使用 sigleResult 是因为已知此定义下该负责人此时的任务只会有一个,否则应该使用 list
    .sigleResult();
// 提交申请本质上也是完成属于自己的任务
taskService.complate(task.getId());
⑤:其他节点负责人查看任务
List<Task> taskList = taskService.createTaskQuery()
                    .processDefinitionKey("流程定义key")
                    .taskAssignee("负责人")
                    .list();
for (Task task : list) {
       System.out.println("流程实例id:" + task.getProcessInstanceId());
       System.out.println("任务id:" + task.getId());
       System.out.println("任务负责人:" + task.getAssignee());
       System.out.println("任务名称:" + task.getName());
}
⑥:负责人提交任务
// 此处的提交分为两种,一种是通过,另一种是拒绝
// 可以由前端数据进行控制,如设置参数 result 0 标识拒绝 1 标识通过
public AjaxResult complateTask(Integer result,String taskId,String ProcessInstanceId){
    // taskId,processInstanceId 为查询个人待处理任务时获得
    if(result == 0){
        // 可以选择直接将流程删除,这样就不会继续进行向下流转                        
        runtimeService.deleteProcessInstance(processInstanceId,"填写删除流程的原因");
    }else{
        // 审批通过就直接提交进行流程流转
        taskService.complate(taskId);
    }
}
⑦:挂起/激活任务
// 挂起或激活需要用到 ProcessInstanceId
ProcessInstance instance =  runtimeService.createProcessInstanceQuery()
       .processInstanceId(ProcessInstanceId)
       // 一个流程实例id对应一个流程
       .singleResult();
// 根据 instance 获取流程状态 
boolean suspended = instance.isSuspended();
if(suspended){
    // 处于挂起状态
    runtimeService.activateProcessInstanceById(processInstanceId);
}eles{
    // 处于激活状态想要挂起
    runtimeService.suspendProcessInstanceById(processInstanceId);
}

⑦:查看历史任务

// 通过 historyService 对象根据负责人获取任务
//(此时获取的任务可能是来自于多个流程,可根据预期设置条件)
List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
                            .taskAssignee("负责人")
                            .list();
for (HistoricActivityInstance hi : activityInstanceList) {
       System.out.println("节点id" + hi.getActivityId());
       System.out.println("节点名称" + hi.getActivityName());
       System.out.println("流程定义id" + hi.getProcessDefinitionId());
       System.out.println("流程实例id" + hi.getProcessInstanceId());
}

三、主要使用的表:

①:act_ru_task:历史的任务实例

②:act_hi_taskinst:运行时任务

③:act_ru_variable:运行时变量

④:act_hi_actinst:历史流程实例

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值