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.条件 ...
随机推荐
- 列表中相同key的字典相加
# 怎么把列表中相同key的字典相加,也就是id的值加id的值,doc_count的值加doc_count的值 # 目标列表 l=[{'id': 5, 'doc_count': 129}, {'id' ...
- Java数据结构——循环链表的实现
//单链表结点类 public class Node<T> { //单链表结点类,T指定结点的元素类型 public T data; //数据域,保存数据元素 public Node< ...
- php与js 编码解码交互
javascript: var fontcolorEncode=encodeURIComponent(fontcolor.value); //编码 php: $fontcolordecode= u ...
- union遇上ntext数据类型
http://www.myhack58.com/Article/html/3/7/2011/31392.htm
- 《Java 程序设计》团队博客第十一周(第一次)
<Java 程序设计>团队博客第十一周(第一次) 团队项目 1.项目内容.目标 项目内容 本组的团队项目准备实现一个有关于大富翁有的游戏程序. 大富翁游戏,以经营权为主要的游戏方式,通过购 ...
- Seccon2017-pwn500-video_player
感觉这个题目并不值500分,有些地方比较牵强,漏洞也比较明显,解题方法有多种,出题者把堆的布局随机化了,不过使用fastbin doublefree的话,可以完全忽视被打乱的堆. from pwn i ...
- SublimeText3 编辑器使用小结
1. 快捷键: Command + shift + D : 复制当前行 Command + shift + K : 删除当前行 Command + J : 合并一行 Command + Enter : ...
- KALI LINUX系统初始化配置
1.Kali Linux安装VirtualBox增强功能 VirtualBox增强功能介绍:物理机与虚拟机之间的文件共享.物理机与虚拟机之间的剪切板共享.虚拟机的direct3D支持,这样虚拟机窗口就 ...
- [BZOJ3733]Iloczyn
Description 给定正整数n和k,问能否将n分解为k个不同正整数的乘积 Input 第一行一个数T(T<=4000)表示测试组数 接下来T行每行两个数n(n<=10^9),k(k& ...
- KindEditor ctrl+v添加图片功能
原理: 监听粘贴事件(paste) 获取粘贴版数据,读取到图片数据流进行加载base64 传到后台服务端直接输出为图片文件保存后返回图片读取路径插入编辑器中 /** * 获取编辑器对象 */ wind ...