Activiti 7学习_1
Activiti7
一、Activiti介绍
Alfresco软件在2010年5月17日宣布Activiti业务流程管理(BPM)开源项目的正式启动,其首席架构师由业务流程管理BPM的专家 Tom Baeyens担任,Tom Baeyens就是原来jbpm的架构师,而jbpm是一个非常有名的工作流引擎,当然activiti也是一个工作流引擎。
Activiti是一个工作流引擎, activiti可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言BPMN2.0进行定义,业务流程按照预先定义的流程进行执行,实现了系统的流程由activiti进行管理,减少业务系统由于流程变更进行系统升级改造的工作量,从而提高系统的健壮性,同时也减少了系统开发维护成本。
Activiti官方网站:https://www.activiti.org/
二、Activiti 7 Demo快速搭建
1、使用IDEA快速搭建一个Maven项目
2、pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dashu</groupId>
<artifactId>activiti-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<activiti.version>7.0.0.Beta1</activiti.version>
</properties>
<dependencies>
<!--activiti 引擎-->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>${activiti.version}</version>
</dependency>
<!--activiti json数据转换 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-json-converter</artifactId>
<version>${activiti.version}</version>
</dependency>
<!--activiti 云支持 -->
<dependency>
<groupId>org.activiti.cloud</groupId>
<artifactId>activiti-cloud-services-api</artifactId>
<version>${activiti.version}</version>
</dependency>
<!--bpmn 模型处理-->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-converter</artifactId>
<version>${activiti.version}</version>
</dependency>
<!--bpmn 布局 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-layout</artifactId>
<version>${activiti.version}</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<!--日志-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
<!--测试-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
3、log4j.properties
log4j.rootLogger=debug,stdout,info,debug,warn,error
#console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= [%d{yyyy-MM-dd HH:mm:ss a}]:%p %l%m%n
#info log
log4j.logger.info=info
log4j.appender.info=org.apache.log4j.DailyRollingFileAppender
log4j.appender.info.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.info.File=./log/info/info.log
log4j.appender.info.Append=true
log4j.appender.info.Threshold=INFO
log4j.appender.info.layout=org.apache.log4j.PatternLayout
log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
#debug log
log4j.logger.debug=debug
log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender
log4j.appender.debug.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.debug.File=./log/debug/debug.log
log4j.appender.debug.Append=true
log4j.appender.debug.Threshold=DEBUG
log4j.appender.debug.layout=org.apache.log4j.PatternLayout
log4j.appender.debug.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
#warn log
log4j.logger.warn=warn
log4j.appender.warn=org.apache.log4j.DailyRollingFileAppender
log4j.appender.warn.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.warn.File=./log/warn/warn.log
log4j.appender.warn.Append=true
log4j.appender.warn.Threshold=WARN
log4j.appender.warn.layout=org.apache.log4j.PatternLayout
log4j.appender.warn.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
#error
log4j.logger.error=error
log4j.appender.error = org.apache.log4j.DailyRollingFileAppender
log4j.appender.error.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.error.File = ./log/error/error.log
log4j.appender.error.Append = true
log4j.appender.error.Threshold = ERROR
log4j.appender.error.layout = org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
4、activiti.cfg.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">
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!--配置数据库相关信息-->
<!--数据库驱动-->
<property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"/>
<!--数据库连接地址-->
<property name="jdbcUrl" value="jdbc:mysql:///activiti?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true"/>
<!--用户名-->
<property name="jdbcUsername" value="root"/>
<!--密码-->
<property name="jdbcPassword" value="123456"/>
<!--
数据库表生成时的策略:
flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。(生产环境常用)
true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。(开发时常用)
create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。(单元测试常用)
drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)。
-->
<property name="databaseSchemaUpdate" value="true"/>
</bean>
</beans>
5、创建数据库
6、创建Activiti的数据库表
(1) 项目结构
(2)ActivitiTest.java测试类
package com.dahu.test;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.apache.log4j.Logger;
import org.junit.jupiter.api.Test;
public class ActivitiTest {
private static Logger logger = Logger.getLogger(ActivitiTest.class);
/**
* 获取Activiti引擎来创建Activiti的数据库表
*/
@Test
public void createActivitiTable() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
logger.info(defaultProcessEngine);
logger.info("创建成功");
}
}
(3)运行结果
三、BPMN文件创建
这里将会使用工具Activiti BPMN visualizer创建BPMN文件
1、Activiti BPMN visualizer插件安装
2、新建BPMN文件
(1)新建一个BPMN文件并打开
(2)画evection工作流
出差申请工作流:
开始事件
用户活动:出差申请创建
受理人:张三
用户活动:组长审核
受理人:李四
用户活动:经理审批
受理人:王五
结束事件
3、BPMN文件
BPMN文件本质上就是一个xml文件,当我们在"Activiti BPMN visualizer"画布上话工作流是,BPMN文件内容也会随之改变。
4、evection.bpmn20.xml
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/processdef">
<process id="evection" name="出差申请工作流" isExecutable="true">
<startEvent id="sid-b294b070-29a3-4b22-9ef6-5583d3230bdf" name="开始"/>
<userTask id="sid-a0b2302c-00ad-4f19-b00e-b6f767bf40d2" name="出差申请创建" activiti:assignee="张三"/>
<userTask id="sid-a665c8ff-8061-4c40-95ab-1329449c97af" name="组长审核" activiti:assignee="李四"/>
<userTask id="sid-d16dd1ab-afb3-4de4-b5ed-c78331cfa615" name="经理审批" activiti:assignee="王五"/>
<endEvent id="sid-fc7d1832-5c28-450f-a9bd-da27f3c0584c" name="结束"/>
<sequenceFlow id="sid-74d23b90-0531-4246-bbe1-c233447fb2c0" sourceRef="sid-b294b070-29a3-4b22-9ef6-5583d3230bdf" targetRef="sid-a0b2302c-00ad-4f19-b00e-b6f767bf40d2"/>
<sequenceFlow id="sid-59b77e24-64e1-4a4a-bcfc-924833e2eddd" sourceRef="sid-a0b2302c-00ad-4f19-b00e-b6f767bf40d2" targetRef="sid-a665c8ff-8061-4c40-95ab-1329449c97af"/>
<sequenceFlow id="sid-8aad1f61-88c9-49b8-bdc2-c3197ca30057" sourceRef="sid-a665c8ff-8061-4c40-95ab-1329449c97af" targetRef="sid-d16dd1ab-afb3-4de4-b5ed-c78331cfa615"/>
<sequenceFlow id="sid-9128fd96-ee22-4fc0-aadd-8738a8d2845f" sourceRef="sid-d16dd1ab-afb3-4de4-b5ed-c78331cfa615" targetRef="sid-fc7d1832-5c28-450f-a9bd-da27f3c0584c"/>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_evection">
<bpmndi:BPMNPlane bpmnElement="evection" id="BPMNPlane_evection">
<bpmndi:BPMNShape id="shape-e164da98-9f11-4606-a083-0e25fad30c73" bpmnElement="sid-b294b070-29a3-4b22-9ef6-5583d3230bdf">
<omgdc:Bounds x="20.0" y="-105.0" width="30.0" height="30.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape-d4d2d39a-596e-491d-9ffc-556a37bace8b" bpmnElement="sid-a0b2302c-00ad-4f19-b00e-b6f767bf40d2">
<omgdc:Bounds x="-15.0" y="-40.0" width="100.0" height="80.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="sid-cb3b86cd-dadb-451a-8e37-424d5eedfaff" bpmnElement="sid-a665c8ff-8061-4c40-95ab-1329449c97af">
<omgdc:Bounds x="-15.0" y="68.75" width="100.0" height="80.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="sid-ab42d20c-2c8e-47c5-978b-d4611b5c1989" bpmnElement="sid-d16dd1ab-afb3-4de4-b5ed-c78331cfa615">
<omgdc:Bounds x="-15.0" y="181.25" width="100.0" height="80.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape-10c8537c-2bef-4528-afdd-9e7ba03f00c7" bpmnElement="sid-fc7d1832-5c28-450f-a9bd-da27f3c0584c">
<omgdc:Bounds x="20.0" y="300.0" width="30.0" height="30.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="edge-ae8594f3-5672-47f9-a967-5079c81ca222" bpmnElement="sid-74d23b90-0531-4246-bbe1-c233447fb2c0">
<omgdi:waypoint x="35.0" y="-75.0"/>
<omgdi:waypoint x="35.0" y="-40.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="edge-89a56d29-17e9-4c74-9c6c-1c325b72272c" bpmnElement="sid-59b77e24-64e1-4a4a-bcfc-924833e2eddd">
<omgdi:waypoint x="35.0" y="40.0"/>
<omgdi:waypoint x="35.0" y="68.75"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="edge-6f3cf344-6694-4f8e-ab47-b55876071838" bpmnElement="sid-8aad1f61-88c9-49b8-bdc2-c3197ca30057">
<omgdi:waypoint x="35.0" y="148.75"/>
<omgdi:waypoint x="35.0" y="181.25"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="edge-0735540b-e25f-48cb-bbf3-b274f50480a3" bpmnElement="sid-9128fd96-ee22-4fc0-aadd-8738a8d2845f">
<omgdi:waypoint x="35.0" y="261.25"/>
<omgdi:waypoint x="35.0" y="300.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
四、工作流部署
1、修改ActivitiTest.java测试类
package com.dahu.test;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.DeploymentBuilder;
import org.apache.log4j.Logger;
import org.junit.jupiter.api.Test;
public class ActivitiTest {
private static Logger logger = Logger.getLogger(ActivitiTest.class);
/**
* 获取Activiti引擎来创建Activiti的数据库表
*/
@Test
public void createActivitiTable() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
logger.info(defaultProcessEngine);
logger.info("创建成功");
}
/**
* 工作流部署
*/
@Test
public void workflowDeployment() {
/**
* 获取Activiti流程引擎
*/
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
/**
* 获取Activiti资源服务
*/
RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
/**
* 资源服务创建一个部署对象
*/
DeploymentBuilder deployment = repositoryService.createDeployment();
/**
* 设置工作流名称
*/
deployment.name("出差申请工作流");
/**
* 添加bpmn资源文件
*/
deployment.addClasspathResource("bpmn/evection.bpmn20.xml");
/**
* 开始部署
*/
deployment.deploy();
// 链式编程
// deployment.name("出差申请工作流")
// .addClasspathResource("bpmn/evection.bpmn20.xml")
// .deploy();
logger.info("工作流部署成功");
}
}
2、运行结果
act_re_deployment表:
act_ge_bytearray表:
五、启动一个工作流实例
1、修改ActivitiTest.java测试类
package com.dahu.test;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.log4j.Logger;
import org.junit.jupiter.api.Test;
public class ActivitiTest {
private static Logger logger = Logger.getLogger(ActivitiTest.class);
/**
* 获取Activiti引擎来创建Activiti的数据库表
*/
@Test
public void createActivitiTable() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
logger.info(defaultProcessEngine);
logger.info("创建成功");
}
/**
* 工作流部署
*/
@Test
public void workflowDeployment() {
/**
* 获取Activiti流程引擎
*/
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
/**
* 获取Activiti资源服务
*/
RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
/**
* 资源服务创建一个部署对象
*/
DeploymentBuilder deployment = repositoryService.createDeployment();
/**
* 设置工作流名称
*/
deployment.name("出差申请工作流");
/**
* 添加bpmn资源文件
*/
deployment.addClasspathResource("bpmn/evection.bpmn20.xml");
/**
* 开始部署
*/
deployment.deploy();
// 链式编程
// deployment.name("出差申请工作流")
// .addClasspathResource("bpmn/evection.bpmn20.xml")
// .deploy();
logger.info("工作流部署成功");
}
/**
* 流程启动
*/
@Test
public void startProcessInstance() {
/**
* 工作流key
*/
String key = "evection";
/**
* 获取Activiti流程引擎
*/
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
/**
* 获取Activiti运行服务
*/
RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();
/**
* 根据工作流key启动一个流程实例
*/
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key);
logger.info("流程定义id = " + processInstance.getProcessDefinitionId());
logger.info("流程实例id = " + processInstance.getId());
logger.info("当前活动id = " + processInstance.getActivityId());
logger.info("流程启动成功....");
}
}
工作流key的来源:
2、运行结果
act_ru_task表:
流程已启动…