activiti 动态自定义流程(包含会签流程)
后台加入工作流步骤(这个不重要,自己实现)
package com.blk.integrated.pojo; import java.io.Serializable;
import java.util.Date; import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table; import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.springframework.format.annotation.DateTimeFormat; import lib.core.utils3.system.CustomDateSerializerHM; @Entity
@Table(name="sys_workflow")
public class SysWorkflow implements Serializable { private static final long serialVersionUID = 1L; @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private Long id; @JsonSerialize(using = CustomDateSerializerHM.class)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
@Column(name="create_time")
private Date createTime;
//工作流名称
@Column(name="name")
private String name;
//工作流描述
@Column(name="content")
private String content; @Column(name="skip_level")
private Integer skipLevel; public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public Date getCreateTime() {
return createTime;
} public void setCreateTime(Date createTime) {
this.createTime = createTime;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
} public Integer getSkipLevel() {
return skipLevel;
} public void setSkipLevel(Integer skipLevel) {
this.skipLevel = skipLevel;
} }
package com.blk.integrated.pojo; import java.io.Serializable;
import java.util.Date; import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table; import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.springframework.format.annotation.DateTimeFormat; import lib.core.utils3.system.CustomDateSerializerHM; @Entity
@Table(name="sys_workflow_step")
public class SysWorkflowStep implements Serializable {
private static final long serialVersionUID = 1L; @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private Long id; @JsonSerialize(using = CustomDateSerializerHM.class)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
@Column(name="create_time")
private Date createTime; @Column(name="workflow_id")
private Long workflowId;
//该步骤审核的角色
@Column(name="role_pkno")
private String rolePkno;
/**
* type==1 会签
* type==2 普通流转
*/
@Column(name="type")
private Integer type; public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public Date getCreateTime() {
return createTime;
} public void setCreateTime(Date createTime) {
this.createTime = createTime;
} public Long getWorkflowId() {
return workflowId;
} public void setWorkflowId(Long workflowId) {
this.workflowId = workflowId;
} public String getRolePkno() {
return rolePkno;
} public void setRolePkno(String rolePkno) {
this.rolePkno = rolePkno;
} public Integer getType() {
return type;
} public void setType(Integer type) {
this.type = type;
} }
//创建模型并部署工作流
package com.blk.back.service.impl; import java.io.File;
import java.io.InputStream;
import java.util.*; import javax.transaction.Transactional; import com.blk.integrated.pojo.SysUserRoleMappingPo;
import lib.core.utils3.StringUtils;
import lib.hibernate.dao.SimpleDao;
import org.activiti.bpmn.BpmnAutoLayout;
import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.blk.back.service.SysWorkflowService;
import com.blk.core.util.RetKit;
/**
*
* @project cb-console-service
* @author suruozhong
* @description (工作流管理)
* @date 2017年10月19日
*/
import com.blk.integrated.dao.SysRoleDao;
import com.blk.integrated.dao.SysWorkflowDao;
import com.blk.integrated.dao.SysWorkflowStepDao;
import com.blk.integrated.pojo.SysRolePo;
import com.blk.integrated.pojo.SysWorkflow;
import com.blk.integrated.pojo.SysWorkflowStep;
@Service
@Transactional
public class SysWorkflowServiceImpl implements SysWorkflowService { @Autowired
private SysRoleDao sysRoleDao;
@Autowired
private SysWorkflowDao sysWorkflowDao;
@Autowired
private SysWorkflowStepDao sysWorkflowStepDao;
@Autowired
private SimpleDao simpleDao;
//获取角色下所有用户
private List<String> getUserRole(String rolePkno){
List<String> list = simpleDao.getDelegate().createSQLQuery("select user_pkno from sys_user_role_mapping where role_pkno=:rolePkno").setParameter("rolePkno",rolePkno).list();
return list;
} @Override
public RetKit save(SysWorkflow model,String stepArr) { model.setCreateTime(new Date());
sysWorkflowDao.getDelegate().save(model);
JSONArray arr = JSONObject.parseArray(stepArr);
List<SysWorkflowStep> stepList = new ArrayList<SysWorkflowStep>();
for(int i=0; i<arr.size();i++) {
SysWorkflowStep step = new SysWorkflowStep();
JSONObject obj = JSONObject.parseObject(arr.get(i).toString());
step.setId(obj.getLong("id"));
step.setCreateTime(new Date());
step.setWorkflowId(model.getId());
step.setRolePkno(obj.getString("rolePkno"));
step.setType(obj.getIntValue("type"));
sysWorkflowStepDao.merge(step);
stepList.add(step);
}
//部署工作流
addFlowDeployment(model,stepList);
return RetKit.ok();
} /**
*@Date:2017/11/24
*@Description:创建流程并部署
*
*/
protected void addFlowDeployment(SysWorkflow workflow,List<SysWorkflowStep> stepList){
System.out.println(".........start...");
ProcessEngine processEngine= ProcessEngines.getDefaultProcessEngine(); // 1. 建立模型
BpmnModel model = new BpmnModel();
Process process=new Process();
model.addProcess(process);
process.setId("news");
process.setName(workflow.getName());
process.setDocumentation(workflow.getContent());
//添加流程
//开始节点
process.addFlowElement(createStartEvent());
for(int i=0; i<stepList.size(); i++){
SysWorkflowStep step = stepList.get(i);
//判断是否会签
if(step.getType()==1){
//会签
//加入并行网关-分支
process.addFlowElement(createParallelGateway("parallelGateway-fork"+i,"并行网关-分支"+i));
//获取角色下所有用户
List<String> userList = getUserRole(step.getRolePkno());
for(int u=0; u<userList.size();u++){
//并行网关分支的审核节点
process.addFlowElement(createUserTask("userTask"+i+u,"并行网关分支用户审核节点"+i+u,userList.get(u)));
}
//并行网关-汇聚
process.addFlowElement(createParallelGateway("parallelGateway-join"+i,"并行网关到-汇聚"+i)); }else{
//普通流转
//审核节点
process.addFlowElement(createGroupTask("task"+i,"组审核节点"+i,step.getRolePkno()));
//回退节点
process.addFlowElement(createUserTask("repulse"+i,"回退节点"+i,"${startUserId}"));
}
}
//结束节点
process.addFlowElement(createEndEvent()); //连线
for(int y=0; y<stepList.size(); y++){
SysWorkflowStep step = stepList.get(y);
//是否会签
if(step.getType()==1){
//会签
//判断是否第一个节点
if(y==0){
//开始节点和并行网关-分支连线
process.addFlowElement(createSequenceFlow("startEvent", "parallelGateway-fork"+y, "开始节点到并行网关-分支"+y, ""));
}else{
//审核节点或者并行网关-汇聚到并行网关-分支
//判断上一个节点是否是会签
if(stepList.get(y-1).getType()==1){
process.addFlowElement(createSequenceFlow("parallelGateway-join"+(y-1),"parallelGateway-fork"+y,"并行网关-汇聚到并行网关-分支"+y,""));
}else{
process.addFlowElement(createSequenceFlow("task"+(y-1),"parallelGateway-fork"+y,"上一个审核节点到并行网关-分支"+y,""));
}
}
//并行网关-分支和会签用户连线,会签用户和并行网关-汇聚连线
List<String> userList = getUserRole(step.getRolePkno());
for(int u=0; u<userList.size(); u++){
process.addFlowElement(createSequenceFlow("parallelGateway-fork"+y,"userTask"+y+u,"并行网关-分支到会签用户"+y+u,""));
process.addFlowElement(createSequenceFlow("userTask"+y+u,"parallelGateway-join"+y,"会签用户到并行网关-汇聚",""));
}
//最后一个节点 并行网关-汇聚到结束节点
if(y==(stepList.size()-1)){
process.addFlowElement(createSequenceFlow("parallelGateway-join"+y,"endEvent","并行网关-汇聚到结束节点",""));
}
}else{
//普通流转
//第一个节点
if(y==0){
//开始节点和审核节点1
process.addFlowElement(createSequenceFlow("startEvent", "task"+y, "开始节点到审核节点"+y, ""));
}else{
//判断上一个节点是否会签
if(stepList.get(y-1).getType()==1){
//会签
//并行网关-汇聚到审核节点
process.addFlowElement(createSequenceFlow("parallelGateway-join"+(y-1),"task"+y,"并行网关-汇聚到审核节点"+y,""));
}else{
//普通
process.addFlowElement(createSequenceFlow("task"+(y-1),"task"+y,"审核节点"+(y-1)+"到审核节点"+y,"${flag=='true'}"));
}
}
//是否最后一个节点
if(y==(stepList.size()-1)){
//审核节点到结束节点
process.addFlowElement(createSequenceFlow("task"+y,"endEvent","审核节点"+y+"到结束节点","${flag=='true'}"));
}
//审核节点到回退节点
process.addFlowElement(createSequenceFlow("task"+y,"repulse"+y,"审核不通过-打回"+y,"${flag=='false'}"));
process.addFlowElement(createSequenceFlow("repulse"+y,"task"+y,"回退节点到审核节点"+y,""));
}
} // 2. 生成的图形信息
new BpmnAutoLayout(model).execute(); // 3. 部署流程
Deployment deployment = processEngine.getRepositoryService().createDeployment().addBpmnModel(process.getId()+".bpmn", model).name(process.getId()+"_deployment").deploy(); // // 4. 启动一个流程实例
// ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey(process.getId());
//
// // 5. 获取流程任务
// List<Task> tasks = processEngine.getTaskService().createTaskQuery().processInstanceId(processInstance.getId()).list();
// try{
// // 6. 将流程图保存到本地文件
// InputStream processDiagram = processEngine.getRepositoryService().getProcessDiagram(processInstance.getProcessDefinitionId());
// FileUtils.copyInputStreamToFile(processDiagram, new File("/deployments/"+process.getId()+".png"));
//
// // 7. 保存BPMN.xml到本地文件
// InputStream processBpmn = processEngine.getRepositoryService().getResourceAsStream(deployment.getId(), process.getId()+".bpmn");
// FileUtils.copyInputStreamToFile(processBpmn,new File("/deployments/"+process.getId()+".bpmn"));
// }catch (Exception e){
// e.printStackTrace();
// } System.out.println(".........end...");
} //任务节点-组
protected UserTask createGroupTask(String id, String name, String candidateGroup) {
List<String> candidateGroups=new ArrayList<String>();
candidateGroups.add(candidateGroup);
UserTask userTask = new UserTask();
userTask.setName(name);
userTask.setId(id);
userTask.setCandidateGroups(candidateGroups);
return userTask;
} //任务节点-用户
protected UserTask createUserTask(String id, String name, String userPkno) {
List<String> candidateUsers=new ArrayList<String>();
candidateUsers.add(userPkno);
UserTask userTask = new UserTask();
userTask.setName(name);
userTask.setId(id);
userTask.setCandidateUsers(candidateUsers);
return userTask;
} //任务节点-锁定者
protected UserTask createAssigneeTask(String id, String name, String assignee) {
UserTask userTask = new UserTask();
userTask.setName(name);
userTask.setId(id);
userTask.setAssignee(assignee);
return userTask;
} /*连线*/
protected SequenceFlow createSequenceFlow(String from, String to,String name,String conditionExpression) {
SequenceFlow flow = new SequenceFlow();
flow.setSourceRef(from);
flow.setTargetRef(to);
flow.setName(name);
if(StringUtils.isNotEmpty(conditionExpression)){
flow.setConditionExpression(conditionExpression);
}
return flow;
} //排他网关
protected ExclusiveGateway createExclusiveGateway(String id,String name) {
ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
exclusiveGateway.setId(id);
exclusiveGateway.setName(name);
return exclusiveGateway;
} //并行网关
protected ParallelGateway createParallelGateway(String id,String name){
ParallelGateway gateway = new ParallelGateway();
gateway.setId(id);
gateway.setName(name);
return gateway;
} //开始节点
protected StartEvent createStartEvent() {
StartEvent startEvent = new StartEvent();
startEvent.setId("startEvent");
return startEvent;
} /*结束节点*/
protected EndEvent createEndEvent() {
EndEvent endEvent = new EndEvent();
endEvent.setId("endEvent");
return endEvent;
} }
部署完流程图
(当前选择两个步骤的流程图)
activiti 动态自定义流程(包含会签流程)的更多相关文章
- Activiti 用户任务并行动态多实例(多用户执行流程)
在很多情况下,我们需要多用户共同执行余下流程,比如开会流程: 领导发起开会,选择开会人员(多个) 每个开会人员接收到通知后需要签到(一名用户签到不会影响到另一位用户的签到) 签到完成后则流程结束 如果 ...
- activiti自定义流程之整合(四):整合自定义表单部署流程定义
综合前几篇博文内容,我想在整合这一部分中应该会有很多模块会跳过不讲,就如自定义表单的表单列表那一块,因为这些模块在整合的过程中都几乎没有什么改动,再多讲也是重复无用功. 正因为如此,在创建了流程模型之 ...
- Activiti工作流学习(二)流程实例、执行对象、任务
一.前言 前面说明了基本的流程部署.定义,启动流程实例等基本操作,下面我们继续来学习流程实例.执行对象.任务. 二.流程实例.执行对象说明 整个Activiti的生命周期经过了如下的几个步骤: 1.流 ...
- Activiti第二篇【管理流程定义、执行任务和流程实例、流程变量】
上篇Activiti只是一个快速入门案例,这篇就讲定义.部署.查看任务等等的一些细节[涉及到的数据库表.对象等等]- 管理流程定义 管理流程定义主要涉及到以下的4张表: -- 流程部署相关的表 SEL ...
- 自定义View分类与流程
自定义View分类与流程(进阶篇)## 转载出处: http://www.gcssloop.com/customview/CustomViewProcess/ 自定义View绘制流程函数调用链(简化版 ...
- 用activiti实现类似钉钉审批流程-附整个系统源码
前言 目前市场上有很多开源平台没有整合工作流,即使有,也是价格不菲的商业版,来看这篇文章的估计也了解了行情,肯定不便宜.我这个快速开发平台在系统基础功能(用户管理,部门管理-)上整合了工作流,你可以直 ...
- Nginx模块开发1_明白自定义模块的编译流程
自定义模块的编译流程 --add-module参数 configure使用--add-module参数指定添加模块目录. config脚本 由--add-module指定的目录保存为$ngx-addo ...
- Activiti进阶(二)——部署流程资源的三种方式
转自:http://blog.csdn.net/zjx86320/article/details/50234707 流程资源可以是各种类型的文件,在启动流程或流程实例运行过程中会被读取.下面介绍常用的 ...
- 【Activiti学习之七】BPMN子流程、顺序流、流程关口
环境 JDK 1.8 MySQL 5.6 Tomcat 7 Eclipse-Luna activiti 6.0 一.子流程 1.嵌入子流程2.调用子流程3.事件子流程4.事务子流程 二.顺序流1.条件 ...
随机推荐
- [笔记]Delphi 2007写DLL供VC调用实例
考虑如下几种常用情况: - VC传入int,返回int- VC传入char *,返回int- VC传入char *,返回char *及int 为简化问题,传递的字符串参数只考虑ANSI格式,不考虑UN ...
- 运输层协议--TCP及UDP协议
TCP及UDP协议 按照网络的五层分级结构来看,TCP及UDP位于运输层,故TCP及UDP是运输层协议.TCP协议--传输控制协议UDP协议--用户数据报协议 多路复用及多路分解 图多路复用及多路分解 ...
- POJ - 1966 Cable TV Network (最大流求点连通度)
题意:求一个无向图的点连通度.点联通度是指,一张图最少删掉几个点使该图不连通:若本身是非连通图,则点连通度为0. 分析:无向图的点连通度可以转化为最大流解决.方法是:1.任意选择一个点作为源点:2.枚 ...
- 【caffe】用训练好的imagenet模型分类图像
因为毕设需要,我首先是用ffmpeg抽取某个宠物视频的关键帧,然后用caffe对这个关键帧中的物体进行分类. 1.抽取关键帧的命令: E:\graduation design\FFMPEG\bin&g ...
- 通过自动回复机器人学Mybatis笔记:接口式编程
[接口式编程]尚未遇见Spring --> 代码量反而增加 1.增加约定,减少犯错的可能(不用直接去写字符串 修改点1:命名空间 修改点2:增加接口,方法名与配置文件中的id对应 package ...
- 在python3下使用OpenCV 抓取摄像头图像提取蓝色
工作中需要对摄像头进行调试, Python平台大大提高调试效率. 从网找到段代码, 可以从摄像头图像中抠出蓝色. import cv2 import numpy as np cap = cv2.Vi ...
- CSS 图片廊
CSS 图片廊 一.示例一 代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...
- Python基本数据类型之列表
学习Python的列表类型需要了解和掌握什么是列表.列表的可变性.列表的访问.列表的增删改查等操作~ 1.了解列表 list1 = ['abc', 123, {1, 2, 3},[2,3]] Pyth ...
- zookeeper可视化管理工具node-zk-browser安装
一.安装nodejs 1. 下载 wget https://github.com/joyent/node/archive/v0.10.35.tar.gz 2. 解压 3. 安装依赖 yum -y in ...
- vs LNK2019 无法解析的外部符号 ***,该符号在函数 WinMain 中被引用
一般链接错误都是因为包含头文件与lib库不匹配(无导出函数.lib库的release debug版本混乱.库引用的优先级.编译器设置mt/mtd等等)造成的. 错误 LNK2019 无法解 ...