1.定义bpmn文件,这个文件里是用来定义流程的
2.发布流程
发布流程,流程的key值相同的情况下每次发布一次,这个流程在数据库的版本会+1
3.查看流程定义
打印的信息
可以看到,我刚才定义的流程已经更新了,现在是版本2了
4.创建流程实例
这里是使用key来创建一个流程
5.查看任务
创建一个实例之后,开始执行流程。一个流程分为很多的节点,每个节点对于不同的人就是不同的任务,所以要运行流程就是从查看自己的任务开始。
在流程定义时我们可以看到 ,start之后,第一个执行事件是提出申请,assignee设定的是 staff
所以查询任务的时候,可以根据staff查看任务
运行代码后,看到了任务相关信息
在数据库中我们可以看到相关信息
6.办理任务
这里的taskId就是上一步查出来的任务id,将任务Id传进taskService.complete的参数中,运行
运行完成后,数据库表中的信息也更新
因为此时流程实例已经走到下一步,此时这个实例的名字是请假审批而不是提出申请了。
然后执行taskId为25002的任务,走到最后一步任务,这个流程实例就完成了。
一定要注意在操作过程中,数据库的变化,这样才能更好更快的理解activiti框架
附代码:
pom.xml引入依赖
<!--- Activiti依赖导入 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>5.18.0</version>
<exclusions>
<exclusion>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--- Activiti依赖导入 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>5.18.0</version>
<exclusions>
<exclusion>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>5.18.0</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</exclusion>
<exclusion>
<artifactId>spring-beans</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>jackson-core-asl</artifactId>
<groupId>org.codehaus.jackson</groupId>
</exclusion>
<exclusion>
<artifactId>commons-lang3</artifactId>
<groupId>org.apache.commons</groupId>
</exclusion>
<exclusion>
<artifactId>mybatis</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
</exclusions>
</dependency>
注意这里的<esclusion> 排除里面相关的依赖
测试类的代码:
public class activitiTest {
/**
* 一条语句创建processEngine, 要求:
* 1、配置文件必须在classpath根目录下
* 2、配置文件名必须为activiti-context.xml或activiti.cfg.xml
* 3、工厂对象的id必须为processEngine
*/
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
HistoryService historyService = processEngine.getHistoryService();
RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
/** 通过zipinputstream完成部署
* 注意:这个的话,需要将bpmn和png文件进行压缩成zip文件,然后放在项目src目录下即可(当然其他目录也可以)
*/
@Test
public void testDeployFromZipinputStream(){
InputStream in = this.getClass().getClassLoader().getResourceAsStream("shenqing.zip");
ZipInputStream zipInputStream = new ZipInputStream(in);
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
processEngine.getRepositoryService()
.createDeployment()
.addZipInputStream(zipInputStream)
.deploy();
}
/**
* 创建ActivitiEngine 生成数据库表
*/
@Test
public void createActivitiEngine(){
//取得ProcessEngineConfiguration对象
ProcessEngineConfiguration engineConfiguration=ProcessEngineConfiguration.
createStandaloneProcessEngineConfiguration();
/**2. 通过加载 activiti.cfg.xml 获取 流程引擎 和自动创建数据库及表*/
// 设置创建表的策略 (当没有表时,自动创建表)
// = "false";//不会自动创建表,没有表,则抛异常
// = "create-drop";//先删除,再创建表
// = "true";//假如没有表,则自动创建
engineConfiguration.setDatabaseSchemaUpdate("true");
//通过ProcessEngineConfiguration对象创建 ProcessEngine 对象
ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
System.out.println("流程引擎创建成功!");
}
/**
* 查看流程图
* 根据deploymentId和name(在act_ge_bytearray数据表中)
*/
@Test
public void testShowImage() throws Exception{
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
InputStream inputStream = processEngine.getRepositoryService()
/**
* deploymentID
* 文件的名称和路径
*/
.getResourceAsStream("110003","activiti/weekReport.bpmn");
OutputStream outputStream3 = new FileOutputStream("e:/weekReport.png");
int b = -1 ;
while ((b=inputStream.read())!=-1){
outputStream3.write(b);
}
inputStream.close();
outputStream3.close();
}
/**
* 根据pdid查看图片(在act_re_procdef数据表中)
* @throws Exception
*/
@Test
public void testShowImage2() throws Exception{
InputStream inputStream = processEngine.getRepositoryService()
.getProcessDiagram("leaveProcess:13:120004");
OutputStream outputStream = new FileOutputStream("e:/leaveProcess.png");
int b = -1 ;
while ((b=inputStream.read())!=-1){
outputStream.write(b);
}
inputStream.close();
outputStream.close();
}
/**
* 部署流程定义
*/
@Test
public void deploy() {
//获取仓库服务 :管理流程定义
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deploy = repositoryService.createDeployment()//创建一个部署的构建器
.addClasspathResource("activiti/weekReport.bpmn")//从类路径中添加资源,一次只能添加一个资源
.name("周报审批流程")//设置部署的名称
.category("直销部")//设置部署的类别
.deploy();
System.out.println("部署的id"+deploy.getId());
System.out.println("部署的名称"+deploy.getName());
}
/**
* 创建流程实例
*/
@Test
public void startProcessInstance(){
String leaveId = "007";
String staffId = "04643";
HashMap<String,Object> map=new HashMap<>();
map.put("staffId",staffId);
// 启动流程
String processInstanceKey = "weekReportProcess";
// 三个参数分别为(String processDefinitionKey, String businessKey, HashMap<String, Object> variables)
ProcessInstance pi = processEngine.getRuntimeService()
.startProcessInstanceByKey(processInstanceKey,leaveId,map);
System.out.println("创建流程实例成功,流程实例id:"+pi.getId()
+ " 流程定义id:" + pi.getProcessDefinitionId());
//默认完成第一步申请人的申请步骤
Task task = processEngine.getTaskService()
.createTaskQuery()
.processInstanceId(pi.getId())
.singleResult();
String nextStaffId = "04646";
map.put("staffId",nextStaffId);
processEngine.getTaskService()
.complete(task.getId(),map);
}
/**
* 查询所有的正在执行的任务
*/
@Test
public void testQueryTask(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
List<Task> tasks = processEngine.getTaskService()
.createTaskQuery()
.list();
for (Task task : tasks) {
System.out.println(task.getName());
}
}
/**
* 根据piid得到当前正在执行的流程实例的正在活动的节点
*/
@Test
public void testActivity(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
* 根据piid得到流程实例
*/
ProcessInstance pi = processEngine.getRuntimeService()
.createProcessInstanceQuery()
.processInstanceId("127501")
.singleResult();
String activityId = pi.getActivityId();//当前流程实例正在执行的activityId
System.out.println(activityId);
}
/**
* 查找个人任务
*/
@Test
public void getMyTaskInfo() {
String staffId = "007";
List<Task> listTask = processEngine.getTaskService()
.createTaskQuery()
.taskAssignee(staffId)
.list();
if (listTask != null && listTask.size() > 0) {
for (Task task : listTask) {
System.out.println("任务ID:"+task.getId());
System.out.println("任务名称:"+task.getName());
System.out.println("任务时间:"+task.getCreateTime());
System.out.println("任务的办理人:"+task.getAssignee());
System.out.println("任务的实例ID:"+task.getProcessDefinitionId());
System.out.println("#########################################");
}
}
}
/**
* 执行任务
* @return
*/
@Test
public void completeMyPersonTask() {
String taskId = "170002";
String nextStaffId = "02222";
HashMap<String,Object> map=new HashMap<>();
map.put("staffId",nextStaffId);
processEngine.getTaskService()
.complete(taskId,map);
System.out.println("查看当前任务成功"+"完成任务,任务ID:" + taskId);
}
/**
* 终止流程实例
* @return
*/
@Test
public void deleteProcessInstance() {
String taskId = "135002";
String reason = "太少了,100个新增!";
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(task.getProcessInstanceId()).singleResult();
processEngine.getRuntimeService()
.deleteProcessInstance(processInstance.getId(),reason);
System.out.println("停止taskId为:" + taskId+"的任务");
}
/**
* 查询执行对象表,使用流程实例ID和当前活动的名称(receivetask1)
*/
@Test
public void queryExecution(){
ProcessInstance pi = processEngine.getRuntimeService()
.createProcessInstanceQuery()
.processDefinitionKey("weekReportProcess")
.singleResult();
//3.查询执行对象表,使用流程实例ID和当前活动的名称(receivetask1)
String processInstanceId = pi.getId();//得到流程实例ID
Execution execution1 = processEngine.getRuntimeService()
.createExecutionQuery()
.processInstanceId(processInstanceId)//流程实例ID
// .activityId("receivetask1")//当前活动的名称
.singleResult();
//5.向后执行一步
processEngine.getRuntimeService()
.signal(execution1.getId());
}
/**
* 直接跳过某一个执行步骤
* @return
*/
@Test
public void passTask() {
String executionId = "127501";
processEngine.getRuntimeService().signal(executionId);
System.out.println("直接执行下一步");
}
/**
* 直接完成执行者为空的步骤,直到有执行者的那一步并设置执行者id
*/
@Test
public void passNull(){
TaskService taskService = processEngine.getTaskService();
//上一个任务的执行者
String assignee = "04646";
//当前流程实例Id
String processInstanceId = "165001";
//整个流程中,所有节点涉及的执行人全部加入到一个数组中
ArrayList<String> assignees= new ArrayList<>();
assignees.add("04643");
assignees.add("04646");
assignees.add("");
assignees.add("007");
//获得上一个执行者后面的数组
List<String> subAssigneeList = assignees.subList(assignees.indexOf(assignee)+1, assignees.size());
//遍历数组 查找下一个执行者是否为空
//如果为空就默认完成进入下一步,直到第一个不为空的执行者 跳出foreach
for (String l:subAssigneeList
) {
System.out.println("subList的位置"+subAssigneeList.indexOf(l)+"元素是:"+l);
//如果 下一个任务的执行人为空,直接默认完成这一步,并根据数组将下一个执行人加入下一个任务中
if (l.equals(null) || l.length() == 0){
Task task = taskService.createTaskQuery()
.processInstanceId(processInstanceId)
.singleResult();
HashMap<String, Object> var = new HashMap<>();
var.put("staffId",subAssigneeList.get( subAssigneeList.indexOf(l) + 1));
taskService.complete(task.getId(),var);
System.out.println("这个位置的执行者是空,直接默认完成这一步");
}else {
System.out.println("存在执行者,跳出此循环");
break;
}
}
System.out.println(subAssigneeList);
}
@Test
public void queryProcessInstanceHistory(){
List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
.orderByHistoricActivityInstanceEndTime()
.desc()
.processInstanceId("132501")
.list();
for (HistoricActivityInstance h:list){
System.out.println(h.getId());
System.out.println(h.getActivityId());
System.out.println(h.getAssignee());
System.out.println(h.getExecutionId());
System.out.println(h.getProcessInstanceId());
System.out.println("##############################");
}
}
}
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcUrl" value="jdbc:sqlserver://xxxDatabaseName=activititest" />
<property name="jdbcDriver" value="" />
<property name="jdbcUsername" value="" />
<property name="jdbcPassword" value="" />
<!-- 建表策略 -->
<!--
"false";不能自动创建表,需要表存在
"create-drop";先删除表再创建表
"true";如果表不存在,自动创建表
-->
<property name="databaseSchemaUpdate" value="true" />
</bean>
</beans>
spring配置文件里可以这么配置
<!-- 配置activiti -->
<context:component-scan base-package="com.wolwo.activiti">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
<context:exclude-filter type="annotation"
expression="org.springframework.web.bind.annotation.ControllerAdvice" />
</context:component-scan>
<!-- 配置流程引擎文件 -->
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="labelFontName" value="宋体"/>
<property name="activityFontName" value="宋体" />
<!-- 是否自动创建23张表 -->
<property name="databaseSchemaUpdate" value="true" />
<property name="jobExecutorActivate" value="false" />
<property name="deploymentResources" value="activiti/**/*.bpmn"/>
</bean>
<!-- 配置创建流程引擎对象 -->
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
<bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
<bean id="formService" factory-bean="processEngine" factory-method="getFormService" />
<bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" />
<bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
<bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
<bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />