关于activiti:Activiti流程预测功能实现

背景某我的项目流程应用activiti开发,现须要开发一个流程预测的性能,流程预测,也称流程预跑,是指用户在发动流程或者执行审批动作时心愿看到流程后续流转的节点,不便用户跟踪流程。Activiti自身不提供流程预测的性能,实际上流程在运行时每一个变量的变动,比方审批后果,表单数据等,都会影响流程的走向,而这些变动是无奈进行预感的,所以流程预测的前提条件就是,咱们须要假如一些变量的值,比拟典型的就是审批后果,咱们须要假如审批后果都是通过的,基于这个前提,咱们能力实现一个能够提供参考价值的预测数据。 实现如果要看懂本文,你必须对activiti开发有根本的理解,对一些根本的概念相熟,倡议先浏览之前发表的Activiti教程流程模型这边筹备了一个简略的报销流程模型示例 流程很简略,提交报销单,我的项目负责人先审批,如果金额小于500,项目经理审批,如果金额大于500,我的项目总监审批,最初财务审核,财务如果回绝间接退回项目经理。其中判断金额的表达式为${amount >500},判断财务审核后果的表达式为${outcome=='REJECT'},并且财务审核这个节点的审批人是一个变量${finApprover} 实现思路计划就是获取到流程模型,代码依据流程模型进行计算流程流转门路,理论审批人,这里须要解决两个问题 流程变量的计算流程模型和节点流向信息的获取参数的获取activiti都有提供相应的api进行获取,为了模拟计算表达式须要在流程中设置变量,这些个别都是在审批代码中动静设置,比方outcome变量,个别都是依据用户的审批后果进行动静设置,这里为了不便模仿,所有参数都是通过流程发动接口传入,在流程发动时事后设置好的 流程发动上面是流程发动的接口代码 @RequestMapping(value = "start", method = RequestMethod.GET)public String start(@RequestParam(value = "processId") String processId, @RequestParam Map params) { ProcessInstance instance = runtimeService.startProcessInstanceByKey(process, params); return instance.getId();}接口承受一个流程id和参数,并且发动时会把参数设置到流程实例中,流程发动须要借助runtimeService 流程预测这边创立了一个bean用于存储每个预测节点信息 ApproveNode.java public class ApproveNode { private String nodeName; private String approvers; public ApproveNode(String nodeName, String approvers) { this.nodeName = nodeName; this.approvers = approvers; } //getter and setter //....}预测的主函数如下 @Servicepublic class PreviewProcessService { @Autowired private RuntimeService runtimeService; @Autowired private TaskService taskService; @Autowired private RepositoryService repositoryService; public List<ApproveNode> getPreviewNodes(String taskId) { /** * 获取待办工作信息 */ Task task = taskService.createTaskQuery() .taskId(taskId) .singleResult(); //获取流程模型 BpmnModel model = repositoryService.getBpmnModel(task.getProcessDefinitionId()); //获取以后节点 FlowElement flowElement = model.getFlowElement(task.getTaskDefinitionKey()); //获取流程变量 Map<String, Object> params = runtimeService.getVariables(task.getExecutionId()); //保留拜访过的节点,防止死循环 Set<String> visitedElements = new HashSet<>(); //递归获取所有预测节点 List<ApproveNode> approveNodes = visiteElement(flowElement, params, visitedElements); return approveNodes; } //....}这里是依据待办id(taskId)获取到流程模型,再获取流程运行时变量进行计算,如果是流程发动时的预跑,间接依据流程id获取模型,流程变量从前端表单传入即可visitedElements为了防止死循环,因为程序须要依据流程连线获取信息进行计算,如果流程自身存在循环,比方下面的例子,财务审批退回给项目经理,项目经理提交后又能够回到财务审核,如果处理不当,就容易呈现死循环这里应用递归进行节点计算,外围逻辑在visiteElement中残缺代码 ...

October 19, 2022 · 3 min · jiezi

关于activiti:SpringBoot-Activiti6系列教程十流程加签征询实现完结篇

加签加签是指以后节点审批完后须要额定再加一个审批人进行审批,额定加的审批用户审批完后流程流转到下一节点。比方失常审批流程为A->B->C,如果B执行了加签动作,那么流程就变为A->B-->D-->C,节点D就是加进来的。 医学上有个万能药叫做安慰剂,没有任何药物作用,可能就是一颗糖果,但患者并不知道,但因患者对医生信赖、患者叫自我暗示以及对某种药物疗效的冀望等而起到镇痛、镇蘸或缓解症状的作用。为什么提到这个呢,因为加签的计划就是一个安慰剂计划,用户感知到加签是从审批历史里感知的,在做加签操作时,审批历史外面记录了加签的动作,然而后盾执行了重新分配(reassign)的操作将以后流程重新分配给另外一个人,达到加签的成果,所以加签就一行代码 taskService.setAssignee(task.getTaskId(), user);这样可能会有以问题 流程图无奈体现加签,因为并没有新的节点产生 如果你的零碎做好了对activiti进行革新的筹备,那么规范的activiti流程图是远远满足不了你的需要的,你须要额定的计划记录审批历史绘制流程图。 咨询之所以把加签和咨询放在一起讲,是因为加签篇幅不够,索性就放到一起。咨询是指,你对以后的流程不是很分明,你须要将流程转发给另外一个人须要另外一个人给你领导,另外一个人审批完后流程回到你这里,你依据他的审批意见进行审批。简略说,如果失常的审批流程为A->B->C,如果B执行了咨询操作,那么流程就变为了A->B-->D-->B->C,咨询和加签的区别就在于,咨询会回到发动咨询的节点,加签不会。 咨询就是两次的重新分配,怎么说呢 B重新分配给DD重新分配给B两次的reassign操作就能够实现咨询,要解决的问题就是怎么协调好这两次重新分配。 B执行咨询操作时,通过变量标记咨询动作,并将咨询人B的信息(次要是账号)保留在变量中D执行回复操作时(流程变为咨询后,被咨询人只有回复的权限),从变量中取出B的账号,从新将流程调配给BB执行失常的审批操作,流程失常流转。B执行咨询操作/** * 咨询 * * @param context * @param task * @param users * @param user * @return */@Overridepublic TaskResponse inquire(TaskResponse task, List<String> users, String user) { Map<String, Object> taskParams = new HashMap<>(); taskParams.put("outcome", "inquire"); taskParams.put("approveUser", user); //执行重新分配操作 taskService.setAssignee(task.getTaskId(), users.get(0)); //标识状态为咨询,须要记录在本地变量中 taskService.setVariableLocal(task.getTaskId(), "status", "inquire"); //记录咨询人信息 taskService.setVariableLocal(task.getTaskId(), "originUser", user); Task t = taskService.createTaskQuery() .taskId(task.getTaskId()) .singleResult(); String instanceId = t.getProcessInstanceId(); return this.taskResponse(t, instanceId);}D执行回复操作/** * 咨询 * * @param context * @param task * @param toUser * @param user * @return */@Overridepublic TaskResponse reply(BPMContextInfo context, TaskResponse task, String toUser, String user) { if (toUser == null) { toUser = (String) taskService.getVariableLocal(task.getTaskId(), "originUser"); } Map<String, Object> taskParams = new HashMap<>(); taskParams.put("outcome", "reply"); taskParams.put("approveUser", user); //执行重新分配操作 taskService.setAssignee(task.getTaskId(), toUser); taskService.removeVariable(task.getTaskId(), "status"); taskService.removeVariable(task.getTaskId(), "originUser"); Task t = taskService.createTaskQuery() .taskId(task.getTaskId()) .singleResult(); String instanceId = t.getProcessInstanceId(); return this.taskResponse(t, instanceId);}通过两次reassign的配合实现咨询操作。 ...

October 19, 2022 · 1 min · jiezi

关于activiti:SpringBoot-Activiti6系列教程九流程回退实现

介绍回退操作是指,将流程退回到上一个节点,基本思路是通过审批历史服务HistoryService找到审批审批的上一节点,而后跟通用回绝操作相似,将流程拨回到该节点,要留神的一个问题是,如果碰到并行审批,在并行线上回退应该回退到哪里呢? 如图,如果审批程序为主管审批->上级领导审批->董事长审批,这时候总监审批执行回退操作,应该回退到哪个节点呢,显然不是董事长,因为这是两个并行互不烦扰的审批,失常应该回退到主管审批这里,所以回退操作应该是基于execution的回退。如果你对ecxecution不理解,你能够查看之前的文章SpringBoot Activiti6系列教程(六)-Execution阐明 因而,计划就是找到该execution的上个审批节点将流程回退到该节点。 实现同样,咱们能够编写一个command的类实现回退 FlowToPreNodeCmdimport com.definesys.mpaas.common.exception.MpaasBusinessException;import org.activiti.bpmn.model.FlowElement;import org.activiti.bpmn.model.FlowNode;import org.activiti.bpmn.model.SequenceFlow;import org.activiti.engine.HistoryService;import org.activiti.engine.RepositoryService;import org.activiti.engine.history.HistoricActivityInstance;import org.activiti.engine.impl.interceptor.Command;import org.activiti.engine.impl.interceptor.CommandContext;import org.activiti.engine.impl.persistence.entity.ExecutionEntity;import org.activiti.engine.task.Task;import java.util.List;/** * @Copyright: Shanghai Definesys Company.All rights reserved. * @Description: * @author: jianfeng.zheng * @since: 2019/9/24 6:11 PM * @history: 1.2019/9/24 created by jianfeng.zheng */public class FlowToPreNodeCmd implements Command<String> { private Task task; public FlowToPreNodeCmd(Task task) { this.task = task; } @Override public String execute(CommandContext context) { FlowElement element = this.getPreNode(this.task, context); if (element == null) { throw new MpaasBusinessException("该节点不能进行退回"); } SequenceFlow flow = this.findAcessSequenceFlow((FlowNode) element); ExecutionEntity executionEntity = context.getExecutionEntityManager().findById(task.getExecutionId()); executionEntity.setCurrentFlowElement(flow); context.getAgenda().planTakeOutgoingSequenceFlowsOperation(executionEntity, true); return executionEntity.getId(); } private FlowElement getPreNode(Task task, CommandContext context) { HistoryService historyService = context.getProcessEngineConfiguration().getHistoryService(); List<HistoricActivityInstance> items = historyService.createHistoricActivityInstanceQuery() .executionId(task.getExecutionId()) .activityType("userTask") .orderByHistoricActivityInstanceStartTime() .desc() .list(); if (items == null || items.size() == 0) { throw new MpaasBusinessException("未找到上一节点"); } String currentAct = task.getTaskDefinitionKey(); String preAct = null; for (int i = 0; i < items.size(); ++i) { HistoricActivityInstance item = items.get(i); if (currentAct.equals(item.getActivityId())) { continue; } preAct = item.getActivityId(); break; } if (preAct == null) { return null; } RepositoryService repositoryService = context.getProcessEngineConfiguration().getRepositoryService(); org.activiti.bpmn.model.Process process = repositoryService.getBpmnModel(task.getProcessDefinitionId()).getMainProcess(); FlowElement node = process.getFlowElement(preAct); return node; } private SequenceFlow findAcessSequenceFlow(FlowNode node) { List<SequenceFlow> flows = node.getIncomingFlows(); if (flows == null || flows.size() == 0) { throw new MpaasBusinessException("上一节点找不到入口"); } //找没有加条件的连线 for (SequenceFlow flow : flows) { if (flow.getConditionExpression() == null) { return flow; } } //如果都没有抉择第一条 return flows.get(0); }}有两个中央须要留神 ...

October 19, 2022 · 2 min · jiezi

关于activiti:SpringBoot-Activiti6系列教程八流程拒绝实现

通用回绝从这章开始,就正式进入activiti的实战开发,应用activiti实现各种审批动作,包含一些中国式流程操作,比方回退,咨询等,这些操作activiti的规范性能是没有的,但因为activiti不算简单,也比拟灵便,因而能够通过一些技巧或者变通的办法实现,这章就探讨通用回绝的实现。为什么叫通用回绝,因为在activiti里,失常的回绝都是通过连接线加条件判断实现,你能够定义一个变量如outcome,回绝的时候给这个变量赋值REJECT,在连接线上设置条件表达式从而实现回绝操作。如图: 项目经理回绝到发起人的表达式为${outcome=='REJECT'},在流程里设置好变量就能实现回绝操作: taskService.setVariable(taskId, "outcome", "approve");taskService.complete(taskId);这种回绝实现形式长处是简略,规范反对,灵活性强,可能从任意节点回绝回任意节点,但毛病也是显著的 个别流程每个节点都有可能回绝,那就意味着每个节点都须要设置判断条件,如果都要回绝回发起人,那么都要跟发起人节点进行连贯,如果节点多的话会大大增加流程图的复杂度,让流程图变成一张“蜘蛛网”。因而咱们须要一个通用回绝的性能,需要是,在任意节点回绝后主动回到发起人节点,发起人从新提交后流程从新开始。 那么面临的两个问题是 流程图中没有发起人节点,怎么造出这个发起人节点流程曾经在流转中了,如何从新流转咱们顺次解决以上两个问题 发起人节点解决activiti提供动静批改流程模型的api,但批改流程模型后全局失效,所有的流程都会受影响,因而就算咱们能通过代码“造出”发起人几点,也是不可取的。其实认真想想,咱们是须要一个发起人节点,还是须要一个审批人是发起人的节点,显然,咱们的需要是前面那个,明确了这个情理后,问题就变得简略了,如何让以后节点的审批人变成发起人,计划能够是这样的: 删除以后节点所有的待办,只保留一个待办将保留下来的那个待办审批人设置为发起人通过以上两个步骤咱们能够实现回绝后将待办转移到发起人那里,当然为了在流程里可能获取到发起人,你应该在流程发动的时候将发起人信息存储到变量中。 那么问题又来了,咱们这是将以后节点伪造成了发起人节点,但假的毕竟是假的,等发起人一审批,就露馅了,因为流程会持续往下走,那么为了达到以假乱真的境地,咱们要持续实现以下两件事 审批接口须要晓得以后节点的审批是否是“伪造”的发起人节点如果审批接口晓得了以后节点的审批是发起人发动的,那么就须要将流程从新拨回到第一个节点第一个需要能够通过设置一个变量进行标识,第二个需要是咱们的下一个议题。 回绝实现代码参考: public TaskResponse reject(TaskResponse task, String user) { //删除所有以后task,保留一个,并且将该task的审批人设为发起人 //设置reject标记 Task t = taskService.createTaskQuery() .taskId(task.getTaskId()) .singleResult(); String instanceId = t.getProcessInstanceId(); List<Task> tasks = taskService.createTaskQuery() .processInstanceId(instanceId) .list(); Task luckyTask = tasks.get(0); managementService.executeCommand(new ExecutionVariableDeleteCmd(t.getExecutionId())); for (int i = 1; i < tasks.size(); ++i) { managementService.executeCommand(new TaskDeleteCmd(tasks.get(i).getId())); managementService.executeCommand(new ExecutionVariableDeleteCmd(tasks.get(i).getExecutionId())); } //将发起人设置为以后审批人 taskService.setAssignee(luckyTask.getId(), (String) taskService.getVariable(luckyTask.getId(), "submitter")); //设置变量标识以后状态是已回绝状态 taskService.setVariable(luckyTask.getId(), "status", "reject"); return this.taskResponse(t, instanceId);}审批的代码参考如下: ...

October 19, 2022 · 2 min · jiezi

关于activiti:SpringBoot-Activiti6系列教程七变量

接上一篇文章,咱们探索了execution的运行机制,activiti里变量的作用域就是通过execution实现,activiti里变量按作用域有以下几种 执行变量(variable)本地变量(LocalVariable)长期变量(TransVariable)执行变量作用域在execution上,本地变量作用域在task上,长期变量不存储数据库,流程进入期待节点(比方UserTask)变量主动革除。 须要应用变量的是RuntimeService和TaskService,本文次要对这两个service中变量的应用做具体阐明,防止在不理解变量应用范畴的状况下,谬误的应用变量,导致流程出错。 变量表构造变量存储在表ACT_RU_VARIABLE上, mysql> describe ACT_RU_VARIABLE;+---------------+---------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+---------------+---------------+------+-----+---------+-------+| ID_ | varchar(64) | NO | PRI | NULL | || REV_ | int(11) | YES | | NULL | || TYPE_ | varchar(255) | NO | | NULL | || NAME_ | varchar(255) | NO | | NULL | || EXECUTION_ID_ | varchar(64) | YES | MUL | NULL | || PROC_INST_ID_ | varchar(64) | YES | MUL | NULL | || TASK_ID_ | varchar(64) | YES | MUL | NULL | || BYTEARRAY_ID_ | varchar(64) | YES | MUL | NULL | || DOUBLE_ | double | YES | | NULL | || LONG_ | bigint(20) | YES | | NULL | || TEXT_ | varchar(4000) | YES | | NULL | || TEXT2_ | varchar(4000) | YES | | NULL | |+---------------+---------------+------+-----+---------+-------+12 rows in set (0.00 sec)NAME_是变量名称,TYPE_是变量类型,依据TYPE_类型会将数据保留到不同的字段里,如TYPE_为string则保留到TEXT_或者TEXT_2中,如果是二进制数据,数据存储到表ACT_GE_BYTEARRAY中,并将id存储到BYTEARRAY_ID_字段上。EXECUTION_ID_、PROC_INST_ID_、TASK_ID_控制变量的作用域,如果TASK_ID_为null则为执行变量,如果不为null则为本地变量。 ...

October 19, 2022 · 4 min · jiezi

关于activiti:Java项目集成工作流引擎解决方案及实例展示前后分离版

前言activiti工作流,企业erp、oa、hr、crm等审批零碎轻松落地,销假审批demo从流程绘制到审批完结实例。 一、我的项目模式springboot+vue+activiti集成了activiti在线编辑器,疾速开发平台,可插拔工作流服务。 二、我的项目介绍本我的项目领有用户治理,部门治理,代码生成,零碎监管,报表,大屏展现,业务审批等性能。性能太强大,只能粗矿的介绍,所见即所得,体验一下吧。 三、工作流1.流程模型绘制进入流程模型菜单,创立流程模型,这里波及到网关流转,须要设置流转条件,咱们这里是三十岁以上的走上面分支,三十岁以下的走下面的分支。点击分支线,设置流转条件即可。${age<=30}。保留后咱们在列表中点击公布即可。 2.流程配置公布后,就到了已公布模型列表,在启用之前,咱们须要先对进行节点设置和关联具体单据。 审批人员能够依据角色,间接指定人,部门,部门负责人,发起人部门负责人来进行配置,基本上满足所有的流转需要,并且能够设置表单变量。 设置流程表单,目前就做了一个销假的测试表单,并且能够对相应角色受权,做到自定义权限。 设置完后启动即可。 3.流程提交填写销假表单 提交单据,优先级分为一般,重要,紧急。音讯告诉能够抉择站内告诉,短信,邮件。 提交之后能够撤回单据。 查看流程流转进度状况。 也能够挂起,删除流程。 4.流程审批办理人审批列表,能够解决单据(驳回或者通过),也能够委托别人待办。 审批通过。 委托别人待代。 审批通过后进入已办列表。 年龄大于30岁,进入上面分支流转。 审批通过。 5.待办信息推送站内音讯推送。 总结下面只是展现了平台的审批流性能,还有其余很多性能没展现进去,本人也写了一些十分好用的组件,做到零碎麻利疾速开发,大大减少开发工夫和老本,目前正在对接挪动端审批。之前因为没有工夫去部署线上测试环境,思考近期部署,目前能够独自找我,近程演示,有须要源码的分割我。q:2500564056。 鸣谢: jeecgboot开源版http://jeecg.com/ 咖啡兔activiti实战https://kafeitu.me/

November 12, 2021 · 1 min · jiezi

关于activiti:Java整合activiti工作流前端适配vue流程在线绘制设计器适配在线表单引擎

前言activiti工作流,企业erp、oa、hr、crm等审批零碎轻松落地,销假审批demo从流程绘制到审批完结实例。 一、我的项目模式springboot+vue+activiti集成了activiti在线编辑器,疾速开发平台,可插拔工作流服务。 二、我的项目介绍本我的项目领有用户治理,部门治理,代码生成,零碎监管,报表,大屏展现,业务审批等性能。性能太强大,只能粗矿的介绍,所见即所得,体验一下吧。 三、工作流1.流程模型绘制进入流程模型菜单,创立流程模型,这里波及到网关流转,须要设置流转条件,咱们这里是三十岁以上的走上面分支,三十岁以下的走下面的分支。点击分支线,设置流转条件即可。${age<=30}。保留后咱们在列表中点击公布即可。 2.流程配置公布后,就到了已公布模型列表,在启用之前,咱们须要先对进行节点设置和关联具体单据。 审批人员能够依据角色,间接指定人,部门,部门负责人,发起人部门负责人来进行配置,基本上满足所有的流转需要,并且能够设置表单变量。 设置流程表单,目前就做了一个销假的测试表单,并且能够对相应角色受权,做到自定义权限。 设置完后启动即可。 3.流程提交填写销假表单 提交单据,优先级分为一般,重要,紧急。音讯告诉能够抉择站内告诉,短信,邮件。 提交之后能够撤回单据。 查看流程流转进度状况。 也能够挂起,删除流程。 4.流程审批办理人审批列表,能够解决单据(驳回或者通过),也能够委托别人待办。 审批通过。 委托别人待代。 审批通过后进入已办列表。 年龄大于30岁,进入上面分支流转。 审批通过。 5.待办信息推送站内音讯推送。 总结下面只是展现了平台的审批流性能,还有其余很多性能没展现进去,本人也写了一些十分好用的组件,做到零碎麻利疾速开发,大大减少开发工夫和老本,目前正在对接挪动端审批。之前因为没有工夫去部署线上测试环境,思考近期部署,目前能够独自找我,近程演示,有须要源码的分割我。q:2500564056。 鸣谢: jeecgboot开源版http://jeecg.com/ 咖啡兔activiti实战https://kafeitu.me/

September 30, 2021 · 1 min · jiezi

关于activiti:activiti流程图在线绘制业务申请审批流转跟进催办springboot集成工作流基础框架

前言目前市场上有很多开源平台没有整合工作流,即便有,也是价格不菲的商业版,来看这篇文章的预计也理解了行情,必定不便宜。我这个疾速开发平台在零碎根底性能(用户治理,部门治理…)上整合了工作流,你能够间接用来开发ERP,OA,CRM等企业级利用,不必再放心如何再去花大量的工夫集成工作流进来。博主是集体开发者。钻研工作流有几年了,依稀记得第一次写工作流是用在江苏某省局的用车申请业务上,那时候年轻气盛,精力充沛可是能力无限,熬了几十个夜整进去了,即便进去了,也是代码很乱。前面也在好几个零碎参加了工作流的开发,目前是独自把这一套给抽取进去了,做成了可插拔的,能够十分不便的整合到你的程序中。上面咱们来摸索吧。 一、我的项目模式springboot+vue+activiti集成了activiti在线编辑器,疾速开发平台,可插拔工作流服务。 二、我的项目介绍本我的项目领有用户治理,部门治理,代码生成,零碎监管,报表,大屏展现,业务审批等性能。性能太强大,只能粗矿的介绍,所见即所得,体验一下吧。 三、工作流1.流程模型绘制进入流程模型菜单,创立流程模型,这里波及到网关流转,须要设置流转条件,咱们这里是三十岁以上的走上面分支,三十岁以下的走下面的分支。点击分支线,设置流转条件即可。${age<=30}。保留后咱们在列表中点击公布即可。 2.流程配置公布后,就到了已公布模型列表,在启用之前,咱们须要先对进行节点设置和关联具体单据。 审批人员能够依据角色,间接指定人,部门,部门负责人,发起人部门负责人来进行配置,基本上满足所有的流转需要,并且能够设置表单变量。 设置流程表单,目前就做了一个销假的测试表单,并且能够对相应角色受权,做到自定义权限。设置完后启动即可。 3.流程提交填写销假表单 提交单据,优先级分为一般,重要,紧急。音讯告诉能够抉择站内告诉,短信,邮件。 提交之后能够撤回单据。查看流程流转进度状况。 也能够挂起,删除流程。 4.流程审批办理人审批列表,能够解决单据(驳回或者通过),也能够委托别人待办。审批通过。委托别人待代。 审批通过后进入已办列表。 年龄大于30岁,进入上面分支流转。 审批通过。 5.待办信息推送站内音讯推送。 总结下面只是展现了平台的审批流性能,还有其余很多性能没展现进去,本人也写了一些十分好用的组件,做到零碎麻利疾速开发,大大减少开发工夫和老本,目前正在对接挪动端审批。之前因为没有工夫去部署线上测试环境,思考近期部署,目前能够独自找我,近程演示,有须要源码的分割我。q:2500564056。 鸣谢:jeecgboot开源版http://jeecg.com/咖啡兔activiti实战https://kafeitu.me/

August 31, 2021 · 1 min · jiezi

关于activiti:springbootvueactiviti在线编辑器快速开发平台

前言目前市场上有很多开源平台没有整合工作流,即便有,也是价格不菲的商业版,来看这篇文章的预计也理解了行情,必定不便宜。我这个疾速开发平台在零碎根底性能(用户治理,部门治理…)上整合了工作流,你能够间接用来开发ERP,OA,CRM等企业级利用,不必再放心如何再去花大量的工夫集成工作流进来。博主是集体开发者。钻研工作流有几年了,依稀记得第一次写工作流是用在江苏某省局的用车申请业务上,那时候年轻气盛,精力充沛可是能力无限,熬了几十个夜整进去了,即便进去了,也是代码很乱。前面也在好几个零碎参加了工作流的开发,目前是独自把这一套给抽取进去了,做成了可插拔的,能够十分不便的整合到你的程序中。上面咱们来摸索吧。 一、我的项目模式springboot+vue+activiti集成了activiti在线编辑器,疾速开发平台,可插拔工作流服务。 二、我的项目介绍本我的项目领有用户治理,部门治理,代码生成,零碎监管,报表,大屏展现,业务审批等性能。性能太强大,只能粗矿的介绍,所见即所得,体验一下吧。 三、工作流1.流程模型绘制进入流程模型菜单,创立流程模型,这里波及到网关流转,须要设置流转条件,咱们这里是三十岁以上的走上面分支,三十岁以下的走下面的分支。点击分支线,设置流转条件即可。${age<=30}。保留后咱们在列表中点击公布即可。 2.流程配置公布后,就到了已公布模型列表,在启用之前,咱们须要先对进行节点设置和关联具体单据。 审批人员能够依据角色,间接指定人,部门,部门负责人,发起人部门负责人来进行配置,基本上满足所有的流转需要,并且能够设置表单变量。 设置流程表单,目前就做了一个销假的测试表单,并且能够对相应角色受权,做到自定义权限。设置完后启动即可。 3.流程提交填写销假表单 提交单据,优先级分为一般,重要,紧急。音讯告诉能够抉择站内告诉,短信,邮件。 提交之后能够撤回单据。查看流程流转进度状况。 也能够挂起,删除流程。 4.流程审批办理人审批列表,能够解决单据(驳回或者通过),也能够委托别人待办。审批通过。委托别人待代。 审批通过后进入已办列表。 年龄大于30岁,进入上面分支流转。 审批通过。 5.待办信息推送站内音讯推送。 总结下面只是展现了平台的审批流性能,还有其余很多性能没展现进去,本人也写了一些十分好用的组件,做到零碎麻利疾速开发,大大减少开发工夫和老本,目前正在对接挪动端审批。之前因为没有工夫去部署线上测试环境,思考近期部署,目前能够独自找我,近程演示,有须要源码的分割我。q:2500564056。 鸣谢:jeecgboot开源版http://jeecg.com/咖啡兔activiti实战https://kafeitu.me/

August 26, 2021 · 1 min · jiezi

关于activiti:Activiti-数据库表结构-ACTHIACTINST

历史节点表(act_hi_actinst)历史流动信息。记录流程流转过的所有节点,与ACT_HI_TASKINST不同的是,ACT_HI_TASKINST只记录usertask内容。 字段名称字段形容数据类型主键为空取值阐明ID_ID_nvarchar(64)√ PROC_DEF_ID_流程定义IDnvarchar(64) 对应表(act_run_execution,act_hi_procinst)PROC_INST_ID_流程实例IDnvarchar(64) 对应表(act_re_procdef)EXECUTION_ID_执行实例IDnvarchar(64) 对应表(act_run_execution)ACT_ID_节点IDnvarchar(225) 节点定义IDTASK_ID_工作实例IDnvarchar(64) √工作实例ID 其余节点类型实例ID在这里为空CALL_PROC_INST_ID_调用内部的流程实例IDnvarchar(64) √调用内部流程的流程实例ID’ACT_NAME_节点名称nvarchar(225) √节点定义名称ACT_TYPE_节点类型nvarchar(225) 如startEvent、userTaskASSIGNEE_签收人nvarchar(64) √节点签收人START_TIME_开始工夫datetime 2013-09-15 11:30:00END_TIME_完结工夫datetime √2013-09-15 11:30:00DURATION_耗时numeric(19,0) √毫秒值

August 25, 2021 · 1 min · jiezi

关于activiti:Activiti-数据库表结构-ACTGEPROPERTY

Activiti 数据库表构造 ACT_GE_PROPERTY属性数据表(act_ge_property) 属性数据表。存储整个流程引擎级别的数据。 字段名称字段形容数据类型主键为空取值阐明NAME_名称nvarchar(64)√ schema.versionschema.historynext.dbidVALUE_值nvarchar(300) √5.create(5.)REV_乐观锁int √version

August 24, 2021 · 1 min · jiezi

关于activiti:Activiti-数据库表结构-ACTGEBYTEARRAY

二进制数据表,存储通用的流程定义和流程资源。 保留流程定义图片和xml、Serializable(序列化)的变量,即保留所有二进制数据。 字段名称字段形容数据类型主键为空取值阐明ID_ID_nvarchar(64)Y 主键IDREV_乐观锁int YVersion(版本)NAME_名称nvarchar(255) Y部署的文件名称,如:leave.bpmn.png,leave.bpmn20.xmlDEPLOYMENT_ID_部署IDnvarchar(64) Y部署表IDBYTES_字节varbinary(max) Y部署文件GENERATED_是否是引擎生成tinyint Y0为用户生成,1为activiti生成

August 23, 2021 · 1 min · jiezi

关于activiti:Activiti数据库表结构

Activiti数据库表构造<u>版本:针对5和6</u> Activiti工作流总共蕴含了23张数据表(当初是25张表,新增了ACT_EVT_LOG和ACT_PROCDEF_INFO) 表名规定Activiti应用到的表都是ACT_结尾的。表名的第二局部用两个字母表明表的用处。 ACT_GE_ (GE) 示意 general 全局通用数据及设置,各种状况都应用的数据。ACT_HI_ (HI) 示意 history 历史数据表,蕴含着程执行的历史相干数据,如完结的流程实例,变量,工作,等等ACT_ID_ (ID) 示意 identity 组织机构,用户记录,流程中应用到的用户和组。这些表蕴含标识的信息,如用户,用户组,等等。ACT_RE_ (RE) 示意 repository 存储,蕴含的是动态信息,如,流程定义,流程的资源(图片,规定等)。ACT_RU_ (RU) 示意 runtime 运行时,运行时的流程变量,用户工作,变量,职责(job)等运行时的数据。Activiti 只存储实例执行期间的运行时数据,当流程实例完结时,将删除这些记录。这就保障了这些运行时的表小且快。25 张表详情个别数据 (ACT_GE_)表名解释ACT_GE_BYTEARRAY二进制数据表,存储通用的流程定义和流程资源。ACT_GE_PROPERTY零碎相干属性,属性数据表存储整个流程引擎级别的数据,初始化表构造时,会默认插入三条记录。流程历史记录 (ACT_HI_)表名解释ACT_HI_ACTINST历史节点表ACT_HI_ATTACHMENT历史附件表ACT_HI_COMMENT历史意见表ACT_HI_DETAIL历史详情表,提供历史变量的查问ACT_HI_IDENTITYLINK历史流程人员表ACT_HI_PROCINST历史流程实例表ACT_HI_TASKINST历史工作实例表ACT_HI_VARINST历史变量表用户用户组表 (ACT_ID_)表名解释ACT_ID_GROUP用户组信息表ACT_ID_INFO用户扩大信息表ACT_ID_MEMBERSHIP用户与用户组对应信息表ACT_ID_USER用户信息表流程定义表 (ACT_RE_)表名解释ACT_RE_DEPLOYMENT部署信息表ACT_RE_MODEL流程设计模型部署表ACT_RE_PROCDEF流程定义数据表运行实例表 (ACT_RU_)表名解释ACT_RU_EVENT_SUBSCR运行时事件 throwEvent、catchEvent 工夫监听信息表ACT_RU_EXECUTION运行时流程执行实例ACT_RU_IDENTITYLINK运行时流程人员表,次要存储工作节点与参与者的相干信息ACT_RU_JOB运行时定时工作数据表ACT_RU_TASK运行时工作节点表ACT_RU_VARIABLE运行时流程变量数据表其它表名解释ACT_EVT_LOG事件日志ACT_PROCDEF_INFO流程定义的动静变更信息

August 20, 2021 · 1 min · jiezi

关于activiti:Activiti流程数据库表含义与常用对象

Activiti流程数据库表含意与罕用对象Activiti框架提供了23张表:Activiti后盾数据库,所有表都以act_结尾。第二局部是示意用处的两个字母标识。第三局部是具体表含意。 act_re_*:'re'示意'repository'。这个前缀的表蕴含了流程定义和流程动态资源 (图片,规定等等)。act_ru_*:'ru'示意'runtime'。这些是运行时的表,蕴含流程实例,工作,变量,异步工作等运行中的数据act_id_*:'id'示意'identity'。这些表蕴含身份信息,比方用户,组等等。act_hi_*:'hi'示意'history'。这些表蕴含历史数据,比方历史流程实例,变量,工作等等。act_ge_*:通用数据,用于不同场景下。个别数据 act_ge_bytearray:二进制数据表act_ge_property:属性数据表存储整个流程引擎级别的数据,初始化表构造时会默认插入三条记录流程定义表 act_re_deployment:部署信息表act_re_model:流程设计模型部署表act_re_procdef:流程定义数据表运行实例表 act_ru_execution:运行时流程执行实例表act_ru_identitylink:运行时流程人员表,次要存储工作节点与参与者的相干信息act_ru_task:运行时工作节点表act_ru_variable:运行时流程变量数据表ACT_RU_EVENT_SUBSCR:运行时事件ACT_RU_JOB:运行时作业流程历史记录 act_hi_actinst:历史节点表act_hi_attachment:历史附件表act_hi_comment:历史意见表act_hi_identitylink:历史流程人员表act_hi_detail :历史详情表,提供历史变量的查问act_hi_procinst:历史流程实例表act_hi_taskinst:历史工作实例表act_hi_varinst:历史变量表用户用户组表 act_id_group :用户组信息表act_id_info:用户扩大信息表act_id_membership:用户与用户组对应信息表act_id_user:用户信息表activiti中的罕用对象:引擎对象 ProcessEngine对象;Activity工作流引擎。这是Activiti工作的外围。负责生成流程运行时的各种实例及数据、监控和治理流程的运行。流程对象 Deployment:部署对象,和部署表(act_re_deployment)对应ProcessDefinition:流程定义对象,和流程定义表(act_re_procdef)对应ProcessInstance:流程实例对象,和流程实例表(act_ru_execution)对应Task:工作对象,和工作表(act_ru_task)对应Service对象 RepositoryService:操作部署、流程定义等动态资源信息RuntimeService:操作流程实例,启动流程实例、查问流程实例、删除流程实例等动静信息TaskService:操作工作,查问工作、办理工作等和工作相干的信息HistoryService:操作历史信息的,查问历史信息IdentityService:操作用户和组Query对象 DeploymentQuery:对应查问部署表(act_re_deployment)ProcessDefinitionQuery:对应查问流程定义表(act_re_procdef)ProcessInstanceQuery:对应查问流程实例表(act_ru_execution)TaskQuery:对应查问工作表(act_ru_task)

August 13, 2021 · 1 min · jiezi

关于activiti:Activiti7事件监听

本文集体博客地址:Activiti7事件监听 (leafage.top) 良久没有记录笔记了,最近做了一些对于工作流的事件,记录一下应用activiti 7的一些教训。需要: 在流程发动和流程操作的过程中,给相干人员发送流程审批的告诉揭示;不要在配置流程时手动增加,不能侵入到流程操作的过程,影响流程执行;<mark>这个怎么动手呢?没搞过activiti,activiti7 的官网文档写的跟屎一样烂,感觉好难呀</mark>... 文档参考性不高,那就试试看官网的示例,找到 activiti 的 repository ,有一个示例 module 叫 activiti-examples,<mark>这里的示例不能间接跑,只能看</mark>,要想跑起来,就复制,粘贴,放到本人的我的项目中。跑题了,说会主题。。。 activiti中的几个关联的重要的类或接口: activiti 中每个流程信息是通过 ProcessInstance 形容,它有这么几个状态:created、started、completed、cancelled、resumed、updated、suspended,与之对应的相干事件形容类是:ProcessCreatedEvent、ProcessStartedEvent、ProcessCompletedEvent、ProcessCancelledEvent、ProcessResumedEvent、ProcessUpdatedEvent、ProcessSuspendedEvent等。 每个流程节点在 activiti 中 通过 Task 来形容,它有这么几个个状态:created、assigned、completed、updated、cancelled、suspended等,与之对应的相干事件形容类是:TaskCreatedEvent、TaskAssignedEvent、TaskCompletedEvent、TaskUpdatedEvent、TaskCancelledEvent、TaskSuspendedEvent等。 如何配置监听器?1. 全局事件监听器:波及到两个类\接口,全局事件监听器 ActivitiEventListener 和 ProcessEngineConfigurationConfigurer(有一个默认的实现类:DefaultActivityBehaviorFactoryMappingConfigurer) ActitiviEventListener 接口有一个 void onEvent(ActivitiEvent activitiEvent) 办法,即在事件状态发生变化时,能够产生的动作都会在这个办法中进行。其源码如下: /** * Describes a class that listens for {@link ActivitiEvent}s dispatched by the engine. * */public interface ActivitiEventListener { void onEvent(ActivitiEvent event); boolean isFailOnException();}ActivitiEvent 蕴含了流程的定义ID,示例ID,执行ID,和事件类型信息,源码如下: public interface ActivitiEvent { ActivitiEventType getType(); String getExecutionId(); String getProcessInstanceId(); String getProcessDefinitionId();}其事件类型包含很多,源码如下: ...

August 13, 2021 · 4 min · jiezi

关于activiti:activiti工作流简单开发平台请假审批例子

前言目前市场上有很多开源平台没有整合工作流,即便有,也是价格不菲的商业版,来看这篇文章的预计也理解了行情,必定不便宜。我这个疾速开发平台在零碎根底性能(用户治理,部门治理…)上整合了工作流,你能够间接用来开发ERP,OA,CRM等企业级利用,不必再放心如何再去花大量的工夫集成工作流进来。博主是集体开发者。钻研工作流有几年了,依稀记得第一次写工作流是用在江苏某省局的用车申请业务上,那时候年轻气盛,精力充沛可是能力无限,熬了几十个夜整进去了,即便进去了,也是代码很乱。前面也在好几个零碎参加了工作流的开发,目前是独自把这一套给抽取进去了,做成了可插拔的,能够十分不便的整合到你的程序中。上面咱们来摸索吧。</font> 一、我的项目模式springboot+vue+activiti集成了activiti在线编辑器,疾速开发平台,可插拔工作流服务。 二、我的项目介绍本我的项目领有用户治理,部门治理,代码生成,零碎监管,报表,大屏展现,业务审批等性能。性能太强大,只能粗矿的介绍,所见即所得,体验一下吧。 三、工作流1.流程模型绘制进入流程模型菜单,创立流程模型,这里波及到网关流转,须要设置流转条件,咱们这里是三十岁以上的走上面分支,三十岁以下的走下面的分支。点击分支线,设置流转条件即可。${age<=30}。保留后咱们在列表中点击公布即可。 2.流程配置公布后,就到了已公布模型列表,在启用之前,咱们须要先对进行节点设置和关联具体单据。 审批人员能够依据角色,间接指定人,部门,部门负责人,发起人部门负责人来进行配置,基本上满足所有的流转需要,并且能够设置表单变量。 设置流程表单,目前就做了一个销假的测试表单,并且能够对相应角色受权,做到自定义权限。设置完后启动即可。 3.流程提交填写销假表单 提交单据,优先级分为一般,重要,紧急。音讯告诉能够抉择站内告诉,短信,邮件。 提交之后能够撤回单据。查看流程流转进度状况。 也能够挂起,删除流程。 4.流程审批办理人审批列表,能够解决单据(驳回或者通过),也能够委托别人待办。审批通过。委托别人待代。 审批通过后进入已办列表。 年龄大于30岁,进入上面分支流转。 审批通过。 5.待办信息推送站内音讯推送。 总结下面只是展现了平台的审批流性能,还有其余很多性能没展现进去,本人也写了一些十分好用的组件,做到零碎麻利疾速开发,大大减少开发工夫和老本,目前正在对接挪动端审批。之前因为没有工夫去部署线上测试环境,思考近期部署,目前能够独自找我,近程演示,有须要源码的分割我。q:2500564056。 鸣谢:jeecgboot开源版http://jeecg.com/咖啡兔activiti实战https://kafeitu.me/

August 9, 2021 · 1 min · jiezi

关于activiti:springbootvueactiviti快速开发平台整合在线流程编辑器

前言目前市场上有很多开源平台没有整合工作流,即便有,也是价格不菲的商业版,来看这篇文章的预计也理解了行情,必定不便宜。我这个疾速开发平台在零碎根底性能(用户治理,部门治理…)上整合了工作流,你能够间接用来开发ERP,OA,CRM等企业级利用,不必再放心如何再去花大量的工夫集成工作流进来。博主是集体开发者。钻研工作流有几年了,依稀记得第一次写工作流是用在江苏某省局的用车申请业务上,那时候年轻气盛,精力充沛可是能力无限,熬了几十个夜整进去了,即便进去了,也是代码很乱。前面也在好几个零碎参加了工作流的开发,目前是独自把这一套给抽取进去了,做成了可插拔的,能够十分不便的整合到你的程序中。上面咱们来摸索吧。</font> 一、我的项目模式springboot+vue+activiti集成了activiti在线编辑器,疾速开发平台,可插拔工作流服务。 二、我的项目介绍本我的项目领有用户治理,部门治理,代码生成,零碎监管,报表,大屏展现,业务审批等性能。性能太强大,只能粗矿的介绍,所见即所得,体验一下吧。 三、工作流1.流程模型绘制进入流程模型菜单,创立流程模型,这里波及到网关流转,须要设置流转条件,咱们这里是三十岁以上的走上面分支,三十岁以下的走下面的分支。点击分支线,设置流转条件即可。${age<=30}。保留后咱们在列表中点击公布即可。 2.流程配置公布后,就到了已公布模型列表,在启用之前,咱们须要先对进行节点设置和关联具体单据。 审批人员能够依据角色,间接指定人,部门,部门负责人,发起人部门负责人来进行配置,基本上满足所有的流转需要,并且能够设置表单变量。 设置流程表单,目前就做了一个销假的测试表单,并且能够对相应角色受权,做到自定义权限。设置完后启动即可。 3.流程提交填写销假表单提交单据,优先级分为一般,重要,紧急。音讯告诉能够抉择站内告诉,短信,邮件。 提交之后能够撤回单据。查看流程流转进度状况。 也能够挂起,删除流程。 4.流程审批办理人审批列表,能够解决单据(驳回或者通过),也能够委托他们待办。审批通过。委托他们待办。 审批通过后进入已办列表。 年龄大于30岁,进入上面分支流转。 审批通过。 5.待办信息推送站内音讯推送。 四、我的项目其余页面截图登录页面 首页用户页面部门治理在线表单生成,代码生成音讯治理统计报表,大屏设计等。 总结下面只是展现了平台的审批流性能,还有其余很多性能没展现进去,本人也写了一些十分好用的组件,做到零碎麻利疾速开发,大大减少开发工夫和老本,目前正在对接挪动端审批,。前因为没有工夫去部署线上测试环境,思考近期部署,目前能够独自找我,近程演示,有须要源码的分割我。q:2500564056。 鸣谢:jeecgboot开源版http://jeecg.com/咖啡兔activiti实战https://kafeitu.me/

May 26, 2021 · 1 min · jiezi

关于activiti:Activiti流程预测功能实现

背景某我的项目流程应用activiti开发,现须要开发一个流程预测的性能,流程预测,也称流程预跑,是指用户在发动流程或者执行审批动作时心愿看到流程后续流转的节点,不便用户跟踪流程。Activiti自身不提供流程预测的性能,实际上流程在运行时每一个变量的变动,比方审批后果,表单数据等,都会影响流程的走向,而这些变动是无奈进行预感的,所以流程预测的前提条件就是,咱们须要假如一些变量的值,比拟典型的就是审批后果,咱们须要假如审批后果都是通过的,基于这个前提,咱们能力实现一个能够提供参考价值的预测数据。 实现如果要看懂本文,你必须对activiti开发有根本的理解,对一些根本的概念相熟,倡议先浏览之前发表的Activiti教程流程模型这边筹备了一个简略的报销流程模型示例 流程很简略,提交报销单,我的项目负责人先审批,如果金额小于500,项目经理审批,如果金额大于500,我的项目总监审批,最初财务审核,财务如果回绝间接退回项目经理。其中判断金额的表达式为${amount >500},判断财务审核后果的表达式为${outcome=='REJECT'},并且财务审核这个节点的审批人是一个变量${finApprover} 实现思路计划就是获取到流程模型,代码依据流程模型进行计算流程流转门路,理论审批人,这里须要解决两个问题 流程变量的计算流程模型和节点流向信息的获取参数的获取activiti都有提供相应的api进行获取,为了模拟计算表达式须要在流程中设置变量,这些个别都是在审批代码中动静设置,比方outcome变量,个别都是依据用户的审批后果进行动静设置,这里为了不便模仿,所有参数都是通过流程发动接口传入,在流程发动时事后设置好的 流程发动上面是流程发动的接口代码 @RequestMapping(value = "start", method = RequestMethod.GET)public String start(@RequestParam(value = "processId") String processId, @RequestParam Map params) { ProcessInstance instance = runtimeService.startProcessInstanceByKey(process, params); return instance.getId();}接口承受一个流程id和参数,并且发动时会把参数设置到流程实例中,流程发动须要借助runtimeService 流程预测这边创立了一个bean用于存储每个预测节点信息 ApproveNode.java public class ApproveNode { private String nodeName; private String approvers; public ApproveNode(String nodeName, String approvers) { this.nodeName = nodeName; this.approvers = approvers; } //getter and setter //....}预测的主函数如下 @Servicepublic class PreviewProcessService { @Autowired private RuntimeService runtimeService; @Autowired private TaskService taskService; @Autowired private RepositoryService repositoryService; public List<ApproveNode> getPreviewNodes(String taskId) { /** * 获取待办工作信息 */ Task task = taskService.createTaskQuery() .taskId(taskId) .singleResult(); //获取流程模型 BpmnModel model = repositoryService.getBpmnModel(task.getProcessDefinitionId()); //获取以后节点 FlowElement flowElement = model.getFlowElement(task.getTaskDefinitionKey()); //获取流程变量 Map<String, Object> params = runtimeService.getVariables(task.getExecutionId()); //保留拜访过的节点,防止死循环 Set<String> visitedElements = new HashSet<>(); //递归获取所有预测节点 List<ApproveNode> approveNodes = visiteElement(flowElement, params, visitedElements); return approveNodes; } //....}这里是依据待办id(taskId)获取到流程模型,再获取流程运行时变量进行计算,如果是流程发动时的预跑,间接依据流程id获取模型,流程变量从前端表单传入即可visitedElements为了防止死循环,因为程序须要依据流程连线获取信息进行计算,如果流程自身存在循环,比方下面的例子,财务审批退回给项目经理,项目经理提交后又能够回到财务审核,如果处理不当,就容易呈现死循环这里应用递归进行节点计算,外围逻辑在visiteElement中残缺代码 ...

January 28, 2021 · 3 min · jiezi

关于activiti:Activiti工作流引擎学习

一、传统工作流实现形式在没有专门的工作流引擎之前,咱们之前为了实现流程管制,通常的做法就是采纳状态字段的值来跟踪流程的变动状况。这样不必角色的用户,通过状态字段的取值来决定记录是否显示。比如说员工销假申请流程:员工申请---部门经理---总经理---人事存档 针对有权限能够查看的记录,以后用户依据本人的角色来决定审批是否合格的操作。如果合格将状态字段设置一个值,来代表合格;当然如果不合格也须要设置一个值来代表不合格的状况。 这是一种最为原始的形式。通过状态字段尽管做到了流程管制,然而当咱们的流程产生变更的时候,这种形式所编写的代码也要进行调整。那么有没有业余的形式来实现工作流的治理呢?并且能够做到业务流程变动之后,咱们的程序能够不必扭转,如果能够实现这样的成果,那么咱们的业务零碎的适应能力就失去了极大晋升。 二、Activiti流程为什么Activiti就能够解决业务需要变更时,源代码不须要更新,更新的是业务流程图,原理是什么? 原理剖析如何能够做到咱们在业务流程产生变更后,咱们的业务零碎代码能够不产生扭转?此时咱们就来剖析一下原理。 具体分析过程如下图所示: Activiti 外部外围机制及实现原理图 原理:节点和表之间的信息转换,关键点就在这里。把节点的信息读取进去而后存入到表里边,未来在解决的时候,从表中读取记录,解决完之后将记录删掉,意味着这个环节就解决完了,而后再解决下一个节点。

December 6, 2020 · 1 min · jiezi

SpringBoot-Activiti6系列教程四流程部署

说明在上一章节中,介绍了如何基于bpmn2.0的xml文件发起流程和获取待办,其中流程文件和代码打包在一起,但实际项目中很少会把流程文件和代码一起打包部署,这样的话,每次流程更新或者发布新流程都需要重新部署应用,因此我们制定了以下部署方案: 提供流程部署接口,可以通过上传流程文件对流程进行部署。如果流程文件没有发生变化,不做新的部署,防止因为重新部署导致版本号上升。资源部署activit部署资源文件需要通过RepositoryService创建一个deployment,通过该deployment进行资源的部署,不单单是bpmn流程文件,activiti可以部署任何文件。 上传资源到activiti@Servicepublic class DeploymentService { @Autowired private RepositoryService repositoryService; /** * deploy resource * * @param name resource name * @param fin resource inputstream * @return */ public String deploy(String name, InputStream fin) { String deploymentId = repositoryService.createDeployment() .addInputStream(name, fin) .name(name) .key(name) .deploy() .getId(); return deploymentId; }}部署的时候指定部署的name和key,方便后续对部署进行进一步操作。 声明restController@RestControllerpublic class DeploymentController { @Autowired private DeploymentService service; @PostMapping(value = "/deploy") public String deploy(@RequestParam("file") MultipartFile file) { try { return service.deploy(file.getOriginalFilename(), file.getInputStream()); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("upload failed"); } }}这里以文件名作为部署的名称,可以根据实际情况指定名称。 ...

September 20, 2019 · 2 min · jiezi

Activiti指南创建流程引擎

创建流程引擎正如之前在maven依赖关系摘要中所建议的,Activiti利用Simple Logging Facade for Java(slf4j)进行日志记录,在此示例应用程序中,我们将使用log4j日志记录实现,将log4j.properties文件添加到项目中。 文件:$mvnProject/src/main/resources/log4j.properties log4j.rootLogger=DEBUG, ACTlog4j.appender.ACT=org.apache.log4j.ConsoleAppenderlog4j.appender.ACT.layout=org.apache.log4j.PatternLayoutlog4j.appender.ACT.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n创建一个新类,包含空的main方法。 文件:$mvnProject/src/main/java/com/example/OnboardingRequest.java package com.example;public class OnboardingRequest { public static void main(String[] args) { }}添加到main入口点的是创建流程引擎,添加到OnboardingRequest.java,如下图所示: package com.example;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngineConfiguration;import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration;public class OnboardingRequest { public static void main(String[] args) { ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration() .setJdbcUrl("jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000") .setJdbcUsername("sa") .setJdbcPassword("") .setJdbcDriver("org.h2.Driver") .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); ProcessEngine processEngine = cfg.buildProcessEngine(); String pName = processEngine.getName(); String ver = ProcessEngine.VERSION; System.out.println("ProcessEngine [" + pName + "] Version: [" + ver + "]"); }}导入Activiti流程引擎和配置。导入独立环境的配置助手(例如,不使用依赖关系管理器)使用基于内存的h2嵌入式数据库创建流程引擎。显示流程引擎配置和Activiti版本。Activiti支持依赖注入: ...

August 19, 2019 · 3 min · jiezi

Online开发初体验JeecgBoot-在线设计流程

Online开发——初体验(在线设计流程) 01 在线设计流程02 在线设计流程和表单对接03 表单业务申请 演示在线设计流程 演示在线设计流程与表单对接 演示业务OA申请

July 16, 2019 · 1 min · jiezi

activiti-工作流activiti-7-中多实例并行会签的实现

在实现并行会签的时候,遇到了奇怪的问题,记录一下方便遇到同样问题的朋友快速解决问题。 问题起源首先,官方文档里提到如何使用多实例,以下是官方提供的sample: <userTask id="miTasks" name="My Task" activiti:assignee="${assignee}"> <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="assigneeList" activiti:elementVariable="assignee" > <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.6 }</completionCondition> </multiInstanceLoopCharacteristics></userTask>解释一下上面的代码,assigneeList 为 集合,例如["kermit", "gonzo", "fozzie"];activiti:elementVariable="assignee" 为 接收 loop 中的值的变量名;activiti:assignee="${assignee}" 相当于将认领人指定为loop中取得的变量对象,就和java 中 foreach 差不多的意思;nrOfInstances:实例总数nrOfActiveInstances:当前活动(即尚未完成)实例的数量。对于顺序多实例,这将始终为1。nrOfCompletedInstances:已完成实例的数量。注意,这三个变量存在当前执行的父执行中。${nrOfCompletedInstances/nrOfInstances >= 0.6 } ,意思不言而喻,就是完成改执行的量大于等于60%就可以通过该节点进入下一节点。 整个这段就是完成会签的雏形。如果完成了60%,我认为绝大部分通过(这里的通过是指完成这个节点任务,和业务上的通过不同。),可以进入下一阶段。 官网就只写到这里。具体可以参考 activiti 用户手册--- 8.5.14。多实例(每个) 然后问题出现了。我参照上列配置,发现nrOfCompletedInstances 始终为0。所以完全没有触发停止循环的条件。 通过跟踪代码,发现当循环中的节点被complete 之后,会经过ParallelMultiInstanceBehavior 这个类的 leave(DelegateExecution execution) 方法 其中一段代码 /** * Called when the wrapped {@link ActivityBehavior} calls the {@link AbstractBpmnActivityBehavior#leave(ActivityExecution)} method. Handles the completion of one of the parallel instances */ public void leave(DelegateExecution execution) { boolean zeroNrOfInstances = false; if (resolveNrOfInstances(execution) == 0) { // Empty collection, just leave. zeroNrOfInstances = true; removeLocalLoopVariable(execution, getCollectionElementIndexVariable()); super.leave(execution); // Plan the default leave execution.setMultiInstanceRoot(false); } int loopCounter = getLoopVariable(execution, getCollectionElementIndexVariable()); int nrOfInstances = getLoopVariable(execution, NUMBER_OF_INSTANCES); int nrOfCompletedInstances = getLoopVariable(execution, NUMBER_OF_COMPLETED_INSTANCES) + 1; int nrOfActiveInstances = getLoopVariable(execution, NUMBER_OF_ACTIVE_INSTANCES) - 1; Context.getCommandContext().getHistoryManager().recordActivityEnd((ExecutionEntity) execution, null); callActivityEndListeners(execution); if (zeroNrOfInstances) { return; } DelegateExecution miRootExecution = getMultiInstanceRootExecution(execution); if (miRootExecution != null) { // will be null in case of empty collection setLoopVariable(miRootExecution, NUMBER_OF_COMPLETED_INSTANCES, nrOfCompletedInstances); setLoopVariable(miRootExecution, NUMBER_OF_ACTIVE_INSTANCES, nrOfActiveInstances); } .......}可以看到这段代码里,nrOfCompletedInstances 是通过getLoopVariable(execution, NUMBER_OF_COMPLETED_INSTANCES)取得然后+1 得到的。那我们猜想,这意思应该就是每次完成后,这个计数器就+1,然后存会到参数当中去,在下面的代码中setLoopVariable(miRootExecution, NUMBER_OF_COMPLETED_INSTANCES, nrOfCompletedInstances);确实也说明他是这样的操作。 ...

June 25, 2019 · 2 min · jiezi

Activiti工作流从入门到入土工作流简介

文章源码托管:https://github.com/OUYANGSIHA...欢迎 star !!!一、activiti介绍Activiti5是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。Activiti基于Apache许可的开源BPM平台,创始人Tom Baeyens是JBoss jBPM的项目架构师,它特色是提供了eclipse插件,开发人员可以通过插件直接绘画出业务流程图。 官网:http://www.activiti.org/下载:http://www.activiti.org/download.html目前,Activiti5中的5.22版本是用的最多的一个版本,本次教程也是使用这个版本进行讲解,最新版本到了7.0版本。 在开始教程之前,我们需要先明确下面的一些概念和知识,可以帮助我们更好的理解工作流的开发。 二、工作流引擎ProcessEngine对象,这是Activiti工作的核心。负责生成流程运行时的各种实例及数据、监控和管理流程的运行。 用百度更为通俗的话来说就是:就是一辆汽车的发动机,就好比一辆汽车,外表做得再漂亮,如果发动机有问题就只是一个摆设。应用系统的弹性就好比引擎转速方面的性能,加速到100 公里需要1 个小时(业务流程发生变动需要进行半年的程序修改)还能叫好车吗?引擎动不动就熄火(程序因为逻辑的问题陷入死循环)的车还敢开吗? 三、BPMN在Activiti工作流中用到了一个BPMN的文件,主要是用来描述业务流程的基本的符号,利用各个组件能够组成一个业务流程图,整个业务也是根据这个图来走的,其实用xml格式打开,就是一个xml文件。 下面就是bpmn组件的示意图 四、数据库在我们进行业务流程开发的时候,是会产生很多的数据的,那么这些数据都是放在哪里呢? 是的,其实就是存放在数据库的。 在Activiti工作流的后台是有数据库的支持的,所有的表都以ACT_开头,利用这些数据库的表,就能够把整个业务流程的数据保存下来,然后利用这些数据进行不同的业务的开发。 数据库表示意图 下面对这些表做一些基本的解释,这些可以先不看,等看完后面的教程后再回过头来看,你会发现其实很简单的。 资源库流程规则表1)act_re_deployment 部署信息表2)act_re_model 流程设计模型部署表3)act_re_procdef 流程定义数据表 运行时数据库表1)act_ru_execution 运行时流程执行实例表2)act_ru_identitylink 运行时流程人员表,主要存储任务节点与参与者的相关信息3)act_ru_task 运行时任务节点表4)act_ru_variable 运行时流程变量数据表 历史数据库表1)act_hi_actinst 历史节点表2)act_hi_attachment 历史附件表3)act_hi_comment 历史意见表4)act_hi_identitylink 历史流程人员表5)act_hi_detail 历史详情表,提供历史变量的查询6)act_hi_procinst 历史流程实例表7)act_hi_taskinst 历史任务实例表8)act_hi_varinst 历史变量表 组织机构表1)act_id_group 用户组信息表2)act_id_info 用户扩展信息表3)act_id_membership 用户与用户组对应信息表4)act_id_user 用户信息表 这些表用的很少,因为我们一般会自己做一个权限管理,所以不会用activiti自身所带的表。 通用数据表1)act_ge_bytearray 二进制数据表2)act_ge_property 属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录。 这两张表的数据是不能够随意删除的,删除可能会出问题。 五、总结工作流的概念就先介绍这么多了,更多的去官网查看,下一节将用一个入门的实例来对工作流进行讲解。 文章有不当之处,欢迎指正,如果喜欢微信阅读,你也可以关注我的微信公众号:好好学java,获取优质学习资源。

June 7, 2019 · 1 min · jiezi

activiti-工作流关于acitiviti-和-spring-boot-集成遇到的一些问题总结

最近在调查activiti工作流的事。项目上打算做一个工作流服务,给微服务中的一些需要流程定义的服务用。所以我尝试用spring boot集成activiti。以下是我调查中遇到的一些问题和一些调查到的结果。 1. activity7 与 activity6 与 activiti cloudactivity cloud 不知道怎么使用,但是看官方解释比较适合云服务(spring cloud)便于扩展,但是activity cloud 貌似是云平台。因为不会搭建,所以就放弃了。activity7 与 activity6 相比,7 多了processruntime与taskruntime 两个类。这两个类需要与security 一起使用,官方里对于TaskRuntime API 有这样一段话: Something important to notice here, is that in order to interact with the TaskRuntime API as a user, you need to have the role: ACTIVITI_USER (Granted Authority: ROLE_ACTIVITI_USER) .因为我项目还没和spring security 集成起来,所以就只好不用这两个类了。我的做法是用activity7 的core,但是还是用 6.0使用方式。 继承方式很简单,在pom里引入就OK了 <activiti-dependencies.version>7.0.0.SR1</activiti-dependencies.version> ... ... <!--activiti starter--> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter</artifactId> </dependency> <!-- Activiti生成流程图 --> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-image-generator</artifactId> </dependency>2. activity 数据表遇到的问题首先是基本25张表 ...

May 31, 2019 · 2 min · jiezi

Activiti6之表结构分析引擎配置及流程部署

关于activiti是什么,我这里就不多说了,我们直接上路,O(∩_∩)O哈哈~ 引擎配置配置方式有好几种:1): /** * 获取默认的流程引擎实例 会自动读取activiti.cfg.xml文件,驱动包,url,数据库用户名,密码写在xml中 */private ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();2):通过java配置,我们这里讲使用 JUnit单元测试,为了更清晰,我们使用Java配置, //流程引擎 private ProcessEngine processEngine; /** * @Description: 数据库初始化 * @param: * @return: void */ @Test public void testProcessEngineConfiguration() { ProcessEngineConfiguration config = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration (); config.setJdbcDriver ("com.mysql.jdbc.Driver"); config.setJdbcUrl("jdbc:mysql://localhost:3306/tx-activiti?characterEncoding=UTF-8&serverTimezone=UTC&nullCatalogMeansCurrent=true"); config.setJdbcUsername("root"); config.setJdbcPassword("root"); //在构建过程引擎时,执行检查并在必要时执行模式的更新. 如果没有表则创建, config.setDatabaseSchemaUpdate (ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); processEngine = config.buildProcessEngine (); } 我们只需要新建好数据库,然后执行上面的 单元测试方法, 然后就会自动在表中新建 28 张表。 如图: 流程引擎创建完成后,只会对 act_ge_property 进行操作, act_ge_property 属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入四条记录, 流程部署测试流程部署,先把上面的流程引擎配置的注解改为@Before。 @Before //@Test public void testProcessEngineConfiguration() { //... }部署流程: ...

April 28, 2019 · 1 min · jiezi