Activiti6工作流入门初体验

简介:

工作流是开发者迈向更高级的一个阶梯,能够帮助我们在更规范清晰的业务场景下更加高效的实现开发工作。

适用场景:

任何一个中间件的引入都会带来额外的复杂度,如果不能正确的认识和使用她,那么她就是累赘。工作流是一个很庞大的中间层,一般用于企业中台的流程管理,保证流程的清晰规范高效的同时,大大减少了开发的工作量。

当我们需要开发一个多角色参与的业务流程时,我们们就需要工作流,如请假审批流程、会议室申请、物资采购流程、网购从下单到物流跟踪签收整个后台流程等

工作流技术现状:

工作流最初都是基于jboss的jbpm,代表性的是activiti和flowable。activiti开发团队解散重组后,部分activiti核心开发人员开启了flowable项目,原开发人员则推进activiti7版本的开发。

网上能找到的工作流学习资料比较少,目前activiti7分别在5月和6月推出了7.1.0M1和M2版本,flowable也到了6.4.1版本,但事实上这两个目前都是还在开发中的半成品。如果想要使用的话,还是寻求稳定版本较好,activiti的稳定版本有5.22和6.0.0,我在这里以6.0.0版本为例介绍下我的学习过程。

 

知识基础:

activiti是以BPMN规范为基础的,所以需要了解BPMN的基础知识,这里只作简单介绍。

bpmn通过流程图和用户交互,用工作流自己的表来维护流程数据,其中activiti是28张表,以act_开头,act_hi_是历史记录类表、act_ru_是运行时流程数据维护表。

BPMN基本对象:

事件event: 代表开始和结束,流程图表示为圆

活动Task(activity):代表处理活动的角色,流程图是一个矩形

网关gateway:代表角色的处理选择,决定流程走向,流程图是一个菱形

流向flow:代表流程图走向,流程图是一个单方向的箭头线

活动任务 Task:

userTask 人机交互任务,必须有人参与操作的任务

ServiceTask Task服务任务,机器自动化

SendTask 发送任务,类似于ServiceTask

ReceiveTask 状态任务,一般用户表示活动状态,需要singal进行流转

ManualTask 线下手工执行任务

BusinessRuleTask 业务规则任务

ScriptTask 脚本任务

AbstractTask 抽象任务

网关 Gateways:

parallel Gateway 并行网关 菱形中一个加号,不会解析条件

Exclusive Gateway 排他网关 菱形或者菱形中一个乘号

Inclusive Gateway 包容网关 菱形中一个圆,走完所有符合条件的flow

 

工作准备:

安装eclipse并安装activiti流程图绘制插件

打开Eclipse -> Help -> Install New SoftWare-> Add

name任意 location:http://www.activiti.org/designer/update/

如果网络不好请架梯子翻墙并反复尝试,网上离线安装的方法我试过了,不可用。

idea玩家可以setting-plugin-actiBPM install下载安装

不过学习阶段不推荐使用idea插件,本人一开始就用的actiBPM,结果画出来的的流程图部署时总是报错,而且actiBPM的表单支持非常糟糕

还有其他的绘图工具如bpmn-js,还在开发中,功能并不完善不推荐

学习开始:

1.流程图工程新建

新建activiti项目:eclipse-文件-新建-其他-activiti-activitiProject

新建activiti空白文件:eclipse-文件-新建-其他-activiti-activitiDiagram

2.使用右侧的画板,画一个简单的审批流程图如图

3.填充流程图信息[重点]

流程图里可以填充的信息选择非常多,每一条信息,在代码中都是有用的,在尝试成功部署运行流程图后,慢慢去理解他每一个配置的意义。此处只展示实现该简单流程需要的配置

3.1文件命名

鼠标点击空白处,填充如下信息,用来命名该bpmn文件的名称和id

3.2userTask审批填充

鼠标点击领导审批矩形框,填充领导审批业务的名称和id

选择属性下的Form-NEW,填写领导审批需要的表单信息,其中type为string,全小写。完成后如图所示

人事审批和重新申请以此类推。

3.3网关flow条件填充

点击领导审批后面的网关指向人事的线,在属性的Main config里填写审批判断条件,此处的tlApprove和之前领导审批Form中的单词大小写要一致

点击该网关指向重新申请的线作同样的修改,其他类推,如图。

填充完毕保存。至此,一个简易的流程就画完了总结下,其实我们必须要填的就两个地方:1.form中xxApprove用于存储用户传给系统的指令(同意/反对)2.网关后面flow的判断条件,写法和jsp一样${xxApprove == flag}

4.搭建一个java工程,部署并运行该流程图

4.1使用idea新建一个普通工程

file-new-project-spring initializr-next...finish;可以把demo改成自己喜欢的名字,如activiti6

4.2添加activiti依赖

在pom文件中添加activiti依赖和h2database依赖

<dependency>
	<groupId>org.activiti</groupId>
	<artifactId>activiti-engine</artifactId>
	<version>6.0.0</version>
</dependency>
<dependency>
	<groupId>com.h2database</groupId>
	<artifactId>h2</artifactId>
	<version>1.3.176</version>
</dependency>

4.3添加bpmn文件

在resource目录下新建一个processes目录,将刚刚eclipse中画好的bpmn文件复制进来

4.4添加日志配置文件

在resource目录下新建一个名为logback.xml的文件,输入如下xml配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <property name="log.dir" scan="true" scanPeriod="30 seconds"/>
    <property name="encoding" value="UTF-8"/>
    <property name="plain" value="%msg%n"/>
    <property name="std" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
    <!-- 控制台输出 -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${plain}</pattern>
            <charset>${encoding}</charset>
        </encoder>
    </appender>
    <!-- 日志输出级别 -->
    <logger name="root">
        <level value="ERROR"/>
    </logger>
    <logger name="com.example">
        <level value="DEBUG"/>
    </logger>
    <root>
        <appender-ref ref="stdout" />
    </root>
</configuration>

 

4.5新建一个测试类用来部署并运行我们的bpmn文件

package com.example.activiti6.generate;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.impl.form.StringFormType;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

/**
 * @ClassName demotest
 * @Description TODO
 * @Author cheng
 * @Date 2019/6/23 13:53
 **/
public class demotest {

    private static final Logger logger = LoggerFactory.getLogger(demotest.class);

    public static void main(String[] args) {
        logger.info("流程启动");
        //创建流程引擎
        ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration().buildProcessEngine();
        logger.info("流程器名称:{};流程器版本号:{}",processEngine.getName(),ProcessEngine.VERSION);
        //部署流程定义文件
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deploy = repositoryService.createDeployment().addClasspathResource("processes/MyProcess.bpmn").deploy();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
        logger.info("流程定义文件名称:{};流程定义文件id:{}",processDefinition.getName(),processDefinition.getId());
        //启动运行流程
        ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceById(processDefinition.getId());
        logger.info("流程实例的定义key:{}",processInstance.getProcessDefinitionKey());
        //处理流程任务
        Scanner scanner = new Scanner(System.in);
        while(processInstance != null && !processInstance.isEnded()){
            TaskService taskService = processEngine.getTaskService();
            List<Task> list = taskService.createTaskQuery().list();
            for (Task task : list) {
                logger.info("待处理任务:{}",task.getName());
                List<FormProperty> formProperties = processEngine.getFormService().getTaskFormData(task.getId()).getFormProperties();
                Map<String,Object> variables = new HashMap<>();
                for (FormProperty formProperty : formProperties) {
                    String line = null;
                    if(StringFormType.class.isInstance(formProperty.getType())){
                        logger.info("请输入:{}",formProperty.getName());
                        line = scanner.nextLine();
                        variables.put(formProperty.getId(),line);
                    }else{
                        logger.info("您输入的类型不支持:{}",formProperty.getType());
                    }
                    logger.info("您输入的内容是:{}",line);
                }
                taskService.complete(task.getId(),variables);
                //查询当前流程实例
                processInstance = processEngine.getRuntimeService().createProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();
            }
            logger.info("待处理任务数量:{}",list.size());
        }
    }
}

5.执行流程

执行结果如下图,本次工作流入门体验完毕,下一节将进一步讲解在工作中如何实际使用activiti完成开发任务

 

本文代码Github地址

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值