springboot整合activti

1.工作流的概念?

工作流:将生活中与审批流程线管的操作,通过计算机的方式去实现。

提供非常晚上的工作流,流程控制等相关功能。

JBPM:JBOSS收购,编程了jboss企业中间件的一员。

activiti:工作流就可以通过这个图形化的步骤去执行程序,这个图形的本质是xml文件。

   activiti工作流是通过解析xml的方式去解析步骤。

图形与xml之间如何进行转化:BPMN2.0

Alfresco 软件在 2010 年 5 月 17 日宣布 Activiti 业务流程管理(BPM)开源项目的正式启动,其 首席架构师由业务流程管理 BPM 的专家 Tom Baeyens 担任,Tom Baeyens 就是原来 jbpm 的架构师, 而 jbpm 是一个非常有名的工作流引擎,当然 activiti 也是一个工作流引擎。 Activiti 是一个工作流引擎, activiti 可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言(BPMN2.0)进行定义,业务系统按照预先定义的流程进行执行,实现了业务系统的业务 流程由 activiti 进行管理,减少业务系统由于流程变更进行系统升级改造的工作量,从而提高系统的 健壮性,同时也减少了系统开发维护成本。

官方网站:https://www.activiti.org/

版本有:5.x,6.x,7.x

2.BPMNJS插件使用及汉化

2.1安装和配置nodejs 插件

2.1.1下载nodejs

https://nodejs.org/en

2.1.2安装nodejs,傻瓜式安装

安装之后在安装目录下创建node_cache和node_global两个目录

如果目录已经存在可以不创建

node_cache:作为缓存路径

node_global:作为全模块所在路径

2.1.3cmd中使用命令修改默认的地址

下面两个地址是上面手动创建的

npm config set prefix  "C:\Program Files\nodejs\node_global"

npm config set cache  "C:\Program Files\nodejs\node_cache"

2.1.4配置nodejs环境变量

位置:右击计算机->属性->高级系统设置->环境变量->系统设置

2.1.5测试nodejs安装情况

如果版本不合适就修改版本号

本案例使用的版本是6.14.18版本

npm install -g npm@6.14.18

2.1.6修改默认的镜像地址

修改命令:npm config set registry https://registry.npm.taobao.org/

3.​​​​​下载和配置BPMNJS插件

3.1​​​​​案例中下载的是7.2.1版本

https://bpmn.io/

3.2直接解压下载的bpmnjs的并进入到目录中

3.3​​​​​​​进入到properties-panel目录中

​​​​​​​在当前目录中打开cmd命令窗口

3.4​​​​​​​在cmd命令行中执行npm install初始化bpmnjs

【执行命令效果如下】

【执行成功后,在propertis-panel目录中产生新的目录】

3.5​​​​​​​在cmd命令行中执行npm run dev命令

命令成功后会直接通过浏览器弹出bpmnjs插件画图工具

默认的访问地址是:http://localhost:9013/

4​​​​​​.BPMNJS插件汉化

4.1在propertis-panel目录中创建目录

在该目录中创建changelanguage文件夹

4.2​​​​​​​将汉化文件放到changelanguage目录中

汉化资源下载:

链接:https://pan.baidu.com/s/1gYTHrKZtgz32HD4C9oKxww

提取码:qzws

4.3​​​​​​​修改默认的配置信息

修改配置主要是修改index.js文件中的默认加载项,将加载项换成是我们刚才拷贝的配置西信息。
【修改默认的配置信息1】
打开properties-panel/app/index.js配置文件
注释以下内容:
import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda';
import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda.json';
替换成:
import propertiesProviderModule from '../changelanguage/properties-panel/provider/activiti';
import activitiModdleDescriptor from '../changelanguage/activiti.json';
import customTranslate from '../changelanguage/customTranslate/customTranslate';
import customControlsModule from '../changelanguage/customControls';
【修改默认配置信息2】
注意以下内容:
var bpmnModeler = new BpmnModeler({
  container: canvas,
  propertiesPanel: {
    parent: '#js-properties-panel'
  },
  additionalModules: [
    propertiesPanelModule,
    propertiesProviderModule
  ],
  moddleExtensions: {
    camunda: camundaModdleDescriptor
  }
});
替换成:
var customTranslateModule = {
    translate: ['value', customTranslate]
};


var bpmnModeler = new BpmnModeler({
    container: canvas,
    propertiesPanel: {
        parent: '#js-properties-panel'
    },
    additionalModules: [
        propertiesPanelModule,
        propertiesProviderModule,
        customControlsModule,
        customTranslateModule
    ],
    moddleExtensions: {
        activiti:activitiModdleDescriptor
    }
});

4.4​​​​​​​在properties-panel目录中打开cmd重新执行命令

在cmd窗口中重新执行npm install 和 npm run dev两个命令

5springboot中使用activti

5.1导入pom依赖

<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>
    </dependencies>

注意因为activti需要操作表,默认使用的是mybatis,所以还要导入mybatis。还有就是activti7是高度集成了springsecurity,所以还要导入spring security的包。

5.2yml文件配置

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/activiti7
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  activiti:
    history-level: audit  #每次重启是否在部署信息表添加一条测试信息。
    db-history-used: true  #是否自动创建历史信息表

5.3使用activti

流程定义-ProcessDefinition和流程实例-ProcessInstance是一对多的关系

重点1:主要是对act_re_deployment和act_re_procedef表的相关操作

Deployement:添加资源文件、获取部署信息、部署时间

ProcessDefinition:获取版本号、key、资源名称、部署ID等。

重点2:RepositoryService:与部署和流程定义相关的service

5.3.1通过zip部署流程实例

//通过zip部署流程实例
@RequestMapping("/deployByZipResources")
@ResponseBody
public  void  deployByZipResources(){
    InputStream in=this.getClass().getClassLoader().getResourceAsStream("bpmn/activiti1.zip");
    ZipInputStream zipInputStream=new ZipInputStream(in);
    Deployment deployment = repositoryService//与部署相关的service
            .createDeployment()//创建部署对象
            .name("请假管理1")
            .addZipInputStream(zipInputStream)
            .deploy();
    System.out.println(deployment.getName());
}

5.3.2查看流程定义信息

//查看流程定义信息
@RequestMapping("/findProcessDefinition")
@ResponseBody
public  void   findProcessDefinition(){
    String deploymentId="236467b5-3271-11ee-86d5-00bb607afddc";
    ProcessDefinition processDefinition=
            repositoryService.createProcessDefinitionQuery()
            .deploymentId(deploymentId)
            .singleResult();
    System.out.println(processDefinition.getVersion());
}

5.3.3级联删除流程定义信息

注:如果想删除所有的流程定义信息,就查询所有的,然后遍历删除

//级联删除流程定义信息
@RequestMapping("/deleteProcessDefinition")
@ResponseBody
public  void  deleteProcessDefinition(){
    String deploymentId="236467b5-3271-11ee-86d5-00bb607afddc";
    repositoryService.deleteDeployment(deploymentId,true);
    System.out.println("====删除成功====");
}

5.3.4查询资源文件信息

//查询资源文件信息
@RequestMapping("/findResources")
@ResponseBody
public void  findResources() throws Exception{
    //得到部署id
    String  deploymentId="c75d6479-3290-11ee-b02c-00bb607afddc";
    //得到资源文件(png,bpmn)--List
    String  resourceName="";
    List<String> resourcesNamelist=repositoryService
            .getDeploymentResourceNames(deploymentId);
    for (int i = 0; i < resourcesNamelist.size(); i++) {
        if(resourcesNamelist.get(i).indexOf(".svg")>0){
            resourceName=resourcesNamelist.get(i);
        }
    }
    //输入流程关联源文件
    InputStream is= repositoryService
            .getResourceAsStream(deploymentId, resourceName);
    //输出流关联目标文件
    FileUtils.copyInputStreamToFile(is, new File("D://aa"+"//"+resourceName));
}

5.3.5​​​​​​​获取最新版的流程定义信息

可以通过version降序排序,第一条就是最新版本
也可以通过map的key不能重复的原理,得到升序的最后一条
/**
	 * 如何查询出最新版本的流程定义
	 */
	@Test
	public  void  queryNewProcessDefinition(){
		String  processDefinitionKey="leaveBill";
		List<ProcessDefinition> list=  processEngine.getRepositoryService()
		.createProcessDefinitionQuery()
		.processDefinitionKey(processDefinitionKey)
		.orderByProcessDefinitionVersion().asc()
		.list();
		Map<String, Object> map=new HashMap<String, Object>();
		for (int i=0;i<list.size();i++) {
			map.put("version",list.get(i).getVersion());
		}
		System.out.println(map.get("version"));;
	}

6流程变量

6.1UEL表达式

EL:Expression Language 表达式语言

UEL:Unified Express Language

语法描述: 统一表达式语言

基本用法:${money>200} 或 ${suggest==’批准’ || suggest==’驳回’}

流程变量表信息:act_run_variable   act_hi_varinst

​​​​​​​6.2URL保留字

and  eq  gt  instanceof  div  or  le  false  empty  not  lt  ge

​​​​​​​6.3UEL运算符

${a+b}  ${a-b}  ${a*b}  ${a div b}  ${a % b }

${a div 0}--Infinity    ${a % 0 }--算数异常

6.4定义流程图

启动任务-使用map参数赋值

//启动流程,并设置办理人信息
@RequestMapping("/startProcessAndSetAssignee")
@ResponseBody
public void  startProcessAndSetAssignee(){
    Map<String,Object> map=new HashMap<>();
    map.put("username","晓春");
    String processDefinitionKey="procss_variable";
    runtimeService.startProcessInstanceByKey(processDefinitionKey,map);
    System.out.println("======启动成功======");
}

办理任务-使用实体类赋值

如果需要使用类传参,在画图时候,流程变量命名为:username.username

且使用的对象需要被序列化

//办理任务,并设置办理人信息
@RequestMapping("/completeAndSetAssignee")
@ResponseBody
public  void  completeAndSetAssignee(){
    Map<String,Object> variables =new HashMap<>();
    String taskId="89949385-34d8-11ee-b9f8-00bb607afddc";
    map.put("username","张三");
taskService.setVariables(taskId,variables);
    taskService.complete(taskId);
    System.out.println("====任务办理成功====");
}
//办理任务,并设置办理人信息
@RequestMapping("/completeAndSetAssignee")
@ResponseBody
public  void  completeAndSetAssignee(){
    Student stu=new Student("1001","张三");
    Map<String,Object> map=new HashMap<>();
    String taskId="5768d71f-34d9-11ee-9c63-00bb607afddc";
    map.put("username",stu);
    taskService.complete(taskId,map);
    System.out.println("====任务办理成功====");
}

7设置流程变量--局部和全局变量

全局流程变量:设置全局流程变量,流程变量名称相同时,后一次的值替换前一次的值,而且可以看到ACT_HI_VARINST和ACT_RU_VARIABLE两张表中的TASK_ID全都为空

局部流程变量:设置局部流程变量,针对当前任务设置流程变量,如果一个流程中存在2个任务,对每个任务都设置局部变量,变量的名称相同时,后一次的版本的值也不会替换前一次版本的值,它会使用不同的任务ID作为标识,存放2个任务的流程变量值,而且可以看到TASK_ID的字段会存放任务ID的值,局部变量不会存入ACT_RU_VARIABLE表,且ACT_HI_VARINST表不会存入数据。

/设置流程变量
@RequestMapping("/setVariable")
@ResponseBody
public  void  setVariable(){
    String taskId="798d60ed-34d9-11ee-b4eb-00bb607afddc";//任务id
    Task task=taskService.createTaskQuery()
            .taskId(taskId)
            .singleResult();
    System.out.println(task.getProcessInstanceId());
    //流程的task与报销自己的业务关联了。
    taskService.setVariable(task.getId(), "报销金额", 10);
    //局部变量
    taskService.setVariableLocal(taskId,  "报销的条目", "总经办支出");
    taskService.setVariableLocal(taskId,  "报销备注", "老总自己买烟");
    //设置pojo类型的参数
    Student stu=new Student("1001", "小春");
    taskService.setVariable(taskId, "stu", stu);
}

查询历史的流程变量信息

//查询当前任务的流程变量信息
@RequestMapping("/getVariable")
@ResponseBody
public void  getVariable(){
    String taskId="798d60ed-34d9-11ee-b4eb-00bb607afddc";
    Integer money=(Integer) taskService.getVariable(taskId, "报销金额");
    System.out.println("==报销金额=="+money);

    //查询对应流程的所有涉及到的变量
    List<HistoricVariableInstance> list= historyService
            .createHistoricVariableInstanceQuery()
            .processInstanceId("77994404-34d7-11ee-a377-00bb607afddc")
            .list();
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i).getVariableName());
    }
}

指定多个候选人

8网关-排他、并行、包容

排他网关通过设置连线条件,只能执行一个任务

并行网关:多个任务同时开启,多个任务都结束,任务结束

包容网关:只要满足条件就启动任务,多个任务都结束,任务结束

事件网关:基于某个事件,如事件,邮箱等

9查询工作流节点的连线信息

启动任务

//查询当前节点的连线信息
@RequestMapping("/getCurrentUserTaskConnection")
@ResponseBody
public void  getCurrentUserTaskConnection(){
    String  taskId="06551f36-34e9-11ee-b663-00bb607afddc";
    // 获取当前任务
    Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
    //获取当前模型
    BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
    // 获取当前节点
    FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
    UserTask userTask = (UserTask)flowElement;
     //获取节点出口线段
    List<SequenceFlow> list = userTask.getOutgoingFlows();
    for (int i=0;i<list.size();i++){
        System.out.println(list.get(i).getName());
    }

}

10总结

我的分享就到这里,下一次分享使用activti7写一个请假的流程网站实例。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值