本文主要讲解如何扩展activiti,使其支持任意属性配置。

先来看下效果

这个流程的分支二这个人员设置,实际存放xml格式如下:

<userTask id="Activity_03o1wx2" name="分支二" workflow:assignee=""><extensionElements><workflow:rules><workflow:field name="assignmentrule"><workflow:string>{"combo":{"type":"sdar"},"advanced":{"dataType":"user"},"handleType":"candidate","handler":"02020072317480678600000101001100","handlerName":"流程发起人","candidate":{"users":[{"value":"25711a8bbcc542f985877c2d09a5d744","name":"王五","lname":"wangwu"}]}}</workflow:string></workflow:field><workflow:field name="transferrule"><workflow:string>{"type":"manual","nodeSelectType":"system","autoCondition":[]}</workflow:string></workflow:field><workflow:field name="handlerule"><workflow:string>{"handleType":"grab","counterSign":{"handleScope":"user"}}</workflow:string></workflow:field><workflow:field name="formrule"><workflow:string>{}</workflow:string></workflow:field></workflow:rules></extensionElements><incoming>Flow_1wjzuu6</incoming><outgoing>Flow_1dv7b8l</outgoing></userTask>

assignmentrule就是我自己定义的办理人员规则,实际使用中我们可以根据我们的需求任务扩展属性,只要设计好我们属性对象的json格式就行,大概看一下我们定义的一些属性规则

"stencil": {"id": "UserTask"
},
"properties": {"overrideid": "applyStep", //自定义ID"name": "申请登记",//节点名称"documentation": "这是申请登记",//节点描述"formrule" :{//表单设置"formType":"dynamic",//表单类型 dynamic:动态 url:在线"urlForm":"/apply/form",//formType为url 时有值"dynamicForm":{//formType为dynamic 时有值"formId":"applyForm",//表单ID"formName":"申请登记单",//表单名称"fields":[{//表单字段设置"fieldId":"applyId",//字段 ID"fieldName":"申请人",//字段 名称"readOnly":true,//是否只读"hidden":false//是否显示}]},"mobileForm":""//手机表单},"assignmentrule": { //分配设置"handler":"zsld", //选择常用处理人是有值"candidate": {//人员选择"users": [{ //候选人"value": "11", //用户ID"name":"张三"//用户名称}, {"value": "22","name":"李四"}],"depts": [{//候选组"value": "33",//机构ID"name":"武汉研发中心"//机构名称}],"roles": [{//修行角色"value": "44",//角色ID"name":"项目经理"//角色名称}]},"advanced":{//高级设置"type":"class", //class:条件类 sql:sql查询 var:变量 rest:restfull接口"classSetting":{//条件类设置"className":"com.cestc.test.Handler",//类"expression": "",//监听表达式"delegateExpression": "",//监听代理表达式"inputParams":[{//输入参数"paramName":"age", //参数名称"paramType":"int", //参数类型"paramValue":"18" //参数值}],"outputResult":{//输出结果变量"value":"conditionResult", //变量值"name":"条件结果" //变量显示}},"restSetting":{"url":"http://test/getValue"},"sqlSetting":{//sql设置"dataSource":"",//数据源"sql":"select count(1) from user" //具体SQL},"varSetting":{//变量条件"varId":"11",//比较变量ID"varName":"年龄",//比较变量名称}}},"handlerule":{//办理设置"handleType":"grab", //grab:抢占 counterSign:会签"counterSign":{//会签设置"type": "Parallel", //Parallel:并行 Sequence:串行"checkAll":true, //是否参与人都要会签完成"passRate": 0.5, //同意比例"rejectBack":true, //结论不同意是否退回"backNode":{//结论不同意退回节点"nodeId":"applyId",//退回节点ID"nodeName":"申请节点"//退回节点名称},"resultVar":{//会签结论变量绑定"varId":"applyId",//绑定变量ID"varName":"申请人"//绑定变量名},"decisionMaker":{//决策人"passDM":[{//同意决策人"value":"11",//决策人ID"name":"张三"}],"rejectDM":[{//拒绝决策人"value":"2","name":"李四"}]}}},"transferrule":{//流转设置"type":"manual",//manual:手动 auto:自动批转 conditionAuto:条件自动批转"autoCondition":"HANDLER_EQ_STARTER,HANDLER_APPEARED"//选择自动审批条件 HANDLER_EQ_STARTER:处理人是发起人 HANDLER_APPEARED:处理人已经出现过 HANDLER_EQ_PRE:处理人与上一步相同HANDLER_NONE:当前节点找不到处理人},"backrule":{ //驳回设置"nodes":[{ //可驳回节点"nodeId":"apply", //节点ID"nodeName":"申请登记"//节点名称}],"backWay":"order"//驳回返回方式 order :按流程图运行 direct:直流回该节点},"recallrule":{//撤回设置"recallType":"none", //none:不能撤回 all://所有节点可撤回  pre_node://前一节点可以撤回"backWay":"order"//撤回返回方式 order :按流程图运行 direct:直流回该节点},"timelimitrule":{//时效规则"timeType":"workday",//workday:工作日 calday:自然日"timeLimit":{ //审批时间限制"day":0, //天"hour":1,//小时"minute":0//分},"timeoutNotify":"imsg,wmsg",//imsg:内部消息 emsg:邮件消息 smsg:短信 wmsg:微信消息"urgeTime":{//催办提前时间"day":0, //天"hour":1,//小时"minute":0//分},"circularUrge":false,"circularUrgeTime":{"day":0, //天"hour":1,//小时"minute":0//分},"urgeNotify":"imsg"//imsg:内部消息 emsg:邮件消息 smsg:短信 wmsg:微信消息},"executionlisteners": {//执行监听"executionListeners": [{"event": "start",//监控事件"implementation": "com.test.userListener",//监听实现"api":"//data/api/getUsers",//网关API"className": "com.test.userListener",//监听实现类"expression": "",//监听表达式"delegateExpression": "",//监听代理表达式"fields": [{//输入参数"name": "fieldName2","implementation": "21233","stringValue": "21233","expression": "","string": ""}, {"name": "fieldName111","implementation": "${dfsd}","stringValue": "","expression": "${dfsd}","string": ""}]}, {"event": "end","implementation": "${testMethod}","className": "","expression": "${testMethod}","delegateExpression": ""}]},"tasklisteners": {//任务监听"taskListeners": [{"event": "create","implementation": "${test}","className": "","expression": "${test}","delegateExpression": "","fields": [{"name": "age","implementation": "18","stringValue": "18","expression": "","string": ""}]}]},"operaterule": {//按钮设置"opbtns": [{//按钮集合"value": "02020061213421486600000101001101", //按钮ID"btnName": "同意"//按钮名称}, {"value": "02020061213421486600000101001102","btnName": "拒绝"}]}}

那是如何实现的呢,主要的原理就是扩展  extensionElements 元素,让各个属性规则以json的格式存放到下面。

参考以前的

writeListeners处理新增 
writeRules

package com.cestc.workflow.core.definition.xmlmodelconverter.converter.export;import com.cestc.workflow.utils.SpringUtil;
import com.cestc.workflow.core.definition.xmlmodelconverter.constants.BpmnXMLConstants;
import com.cestc.workflow.core.engine.util.BpmnXMLUtil;
import com.cestc.workflow.core.model.*;
import com.cestc.workflow.core.engine.rulemanager.converter.RuleConverter;
import com.fasterxml.jackson.databind.ObjectMapper;import javax.xml.stream.XMLStreamWriter;
import java.util.Map;/*** 规则解析,对应extensionElements下的workflow:rules标签*/
public class WorkflowRuleExport implements BpmnXMLConstants {public static boolean writeRules(BaseElement element, boolean didWriteExtensionStartElement, XMLStreamWriter xtw) throws Exception {didWriteExtensionStartElement = writeRules(ELEMENT_RULES, element, didWriteExtensionStartElement, xtw);return didWriteExtensionStartElement;}private static boolean writeRules(String xmlElementName, BaseElement element, boolean didWriteExtensionStartElement, XMLStreamWriter xtw) throws Exception {if (!didWriteExtensionStartElement) {xtw.writeStartElement(ELEMENT_EXTENSIONS);didWriteExtensionStartElement = true;}xtw.writeStartElement(WF_EXTENSIONS_PREFIX, xmlElementName, WF_EXTENSIONS_NAMESPACE);for (Map.Entry<String, RuleConverter> entry : RuleConverter.ruleConverterMap.entrySet()) {if (entry.getValue().getRule(element) != null) {xtw.writeStartElement(WF_EXTENSIONS_PREFIX, ELEMENT_FIELD, WF_EXTENSIONS_NAMESPACE);BpmnXMLUtil.writeDefaultAttribute(ATTRIBUTE_FIELD_NAME, entry.getKey(), xtw);xtw.writeStartElement(WF_EXTENSIONS_PREFIX, ELEMENT_FIELD_STRING, WF_EXTENSIONS_NAMESPACE);xtw.writeCData(SpringUtil.getBean(ObjectMapper.class).writeValueAsString(entry.getValue().getRule(element)));xtw.writeEndElement();xtw.writeEndElement();}}xtw.writeEndElement();return didWriteExtensionStartElement;}}

参考listenerParse 新增worflowRuleParase


package com.cestc.workflow.core.definition.xmlmodelconverter.converter.parser.child;import com.cestc.workflow.core.model.*;
import com.cestc.workflow.core.model.Process;
import com.cestc.workflow.core.engine.rulemanager.converter.RuleConverter;
import org.springframework.util.CollectionUtils;import javax.xml.stream.XMLStreamReader;/*** 元素规则解析** @author liubo*/
public class WorkflowRuleParser extends BaseChildElementParser {@Overridepublic String getElementName() {return ELEMENT_RULES;}@Overridepublic void parseChildElement(XMLStreamReader xtr, BaseElement parentElement, BpmnModel model) throws Exception {boolean readyWithChildElements = false;BaseChildElementParser parser = new FieldExtensionParser();WorkflowRule workflowRule = new WorkflowRule();while (readyWithChildElements == false && xtr.hasNext()) {xtr.next();if (xtr.isStartElement()) {if (parser.getElementName().equals(xtr.getLocalName())) {parser.parseChildElement(xtr, workflowRule, model);}} else if (xtr.isEndElement() && getElementName().equalsIgnoreCase(xtr.getLocalName())) {readyWithChildElements = true;}}if (parentElement instanceof UserTask || parentElement instanceof SequenceFlow || parentElement instanceof Process || parentElement instanceof TimerEventDefinition || parentElement instanceof ServiceTask) {if (!CollectionUtils.isEmpty(workflowRule.getFieldExtensions())) {workflowRule.getFieldExtensions().stream().forEach(fieldExtension -> {RuleConverter converter = RuleConverter.ruleConverterMap.get(fieldExtension.getFieldName());if (converter != null) {converter.convertJsonToRule(parentElement, fieldExtension.getStringValue());}});}}}}

定义规则转换处理类负责各个属性规则的处理就行了

package com.cestc.workflow.core.engine.rulemanager.converter;import com.cestc.workflow.core.model.BaseElement;
import com.cestc.workflow.core.model.UserTask;
import com.cestc.workflow.core.definition.TaskDefinition;
import com.fasterxml.jackson.databind.JsonNode;import java.util.HashMap;
import java.util.Map;/*** 规则转换* @author breeze* @since 2020/7/16 19:33*/
public abstract class RuleConverter {public static Map<String, RuleConverter> ruleConverterMap = new HashMap<String, RuleConverter>();public static final String NODE_FORM_RULE = "formrule";public static final String NODE_ASSIGNMENT_RULE = "assignmentrule";public static final String NODE_HANDLE_RULE = "handlerule";public static final String NODE_BACK_RULE = "backrule";public static final String NODE_RECALL_RULE = "recallrule";public static final String NODE_TRANSFER_RULE = "transferrule";public static final String NODE_OPERATE_RULE = "operaterule";public static final String NODE_TIMELIMIT_RULE = "timelimitrule";public static final String NODE_VAR_RULE = "varrule";public static final String NODE_CONDITION_RULE = "conditionrule";public static final String NODE_APP_RULE="apprule";public static final String NODE_TIMER_RULE="timerrule";public static final String NODE_SAVE_RULE="saverule";public static final String NODE_APIPARAM_RULE="apiparamrule";public static final String NODE_CUSTOMBTN_RULE="custombtnrule";public static final String NODE_FLOWDURATION_RULE="flowdurationrule";public static final String NODE_APPROVE_RULE="approverule";public static final String NODE_SELECT_RULE="nodeselectrule";static{ruleConverterMap.put(NODE_FORM_RULE,new FormRuleConverter());//表单规则ruleConverterMap.put(NODE_ASSIGNMENT_RULE,new AssignmentRuleConverter());//分配规则ruleConverterMap.put(NODE_HANDLE_RULE,new HandleRuleConverter());//办理规则ruleConverterMap.put(NODE_BACK_RULE,new BackRuleConverter());//回退规则ruleConverterMap.put(NODE_RECALL_RULE,new RecallRuleConverter());//撤回规则ruleConverterMap.put(NODE_TRANSFER_RULE,new TransferRuleConverter());//流转规则ruleConverterMap.put(NODE_OPERATE_RULE,new OperateRuleConverter());//操作规则ruleConverterMap.put(NODE_TIMELIMIT_RULE,new TimeLimitRuleConverter());//时效规则ruleConverterMap.put(NODE_VAR_RULE,new VarRuleConverter());//流程变量规则ruleConverterMap.put(NODE_CONDITION_RULE,new ConditionRuleConverter());//连线条件规则ruleConverterMap.put(NODE_SAVE_RULE,new SaveRuleConverter());//保存分类ruleConverterMap.put(NODE_TIMER_RULE,new TimerRuleConverter());//定时设置分类ruleConverterMap.put(NODE_APP_RULE,new AppRuleConverter());//保存分类ruleConverterMap.put(NODE_APIPARAM_RULE,new ApiParamRuleConverter());//api参数规则ruleConverterMap.put(NODE_CUSTOMBTN_RULE,new CustomBtnRuleConverter());//自定义按钮参数规则ruleConverterMap.put(NODE_FLOWDURATION_RULE,new FlowDurationRuleConverter());//流程期限参数规则ruleConverterMap.put(NODE_APPROVE_RULE,new ApproveRuleConverter());//审批规则// 节点选择模式ruleConverterMap.put(NODE_SELECT_RULE, new NodeSelectRuleConverter());}public abstract void convertJsonToElement(JsonNode objectNode, BaseElement element);public abstract String getNodeFlag();public abstract Object getRule(BaseElement element);public abstract void convertJsonToRule(BaseElement element, String ruleJsonStr);public abstract void copyTaskToDefinition(TaskDefinition taskDefinition, UserTask userTask);
}

更多源码见 https://gitee.com/wtr/workflow

扩展activiti 支持任意属性扩展相关推荐

  1. 让IIS支持任意扩展名和未知扩展名的下载

    在IIS6中新增可下载文件类型 IIS 6.0 不能处理未知的 MIME 类型 IIS6 只为对具有已知文件扩展名的文件的请求提供服务.如果请求内容的文件扩展名未映射到已知的扩展,则服务器拒绝请求.即 ...

  2. 爱上MVC~为DisplayNameFor添加扩展,支持PagedList集合

    DisplayNameFor方法是MVC提供给我们的,它可以将模型的DisplayName特性的值显示到页面上,这对程序员来说很是方便,在进行实体设计时,可以指定它的显示名称,然后MVC引擎会自动帮助 ...

  3. 【Kotlin】Kotlin 领域特定语言 DSL 原理 一 ( DSL 简介 | 函数 / 属性扩展 )

    文章目录 I . DSL 简介 II . Kotlin 函数扩展 III . Kotlin 属性扩展 I . DSL 简介 1 . DSL ( Domain Specific Language ) 领 ...

  4. 如何让IIS支持未知文件扩展名下载(转)

    下面让IIS6支持caj文件格式下载: 要为特定扩展名定义 MIME 类型,请按照下列步骤操作: 1. 打开 IIS Microsoft 管理控制台 (MMC),右键单击本地计算机名称,然后单击&qu ...

  5. Cocos Store 插件升级,支持联网功能扩展和微信小游戏适配

    年前 Cocos Store 刚上线一款功能强大的新插件,其提供者 Matchvs 游戏云是国内一家游戏联网服务引擎,用户通过接入 Matchvs-SDK,即可将 Cocos 项目方便快速地导入,并轻 ...

  6. 【Kotlin】扩展属性 ( 扩展变量属性 | 扩展常量属性 | 注意事项 | 本质分析 )

    文章目录 I . 扩展属性 总结 II . 扩展属性 定义格式 III . 扩展属性 标准示例 IV . 扩展属性 注意事项 V . 扩展属性 本质分析 VI . 扩展属性 代码示例解析 I . 扩展 ...

  7. php 7 pcntl扩展,PHP_Linux系统中为php添加pcntl扩展,pcntl扩展可以支持php的多线程 - phpStudy...

    Linux系统中为php添加pcntl扩展 pcntl扩展可以支持php的多线程操作(仅限linux) 原本需要重新编译PHP的后面configrue提示加上--enable-pcntl 由于我的ph ...

  8. ADO.NET 【属性扩展】性别、年龄、编号

    1.性别属性扩展 private bool _Sex; //成员变量public bool Sex // 属性 {get { return _Sex; }set { _Sex = value; }}p ...

  9. android自定义dialog开源库,android-dialog: 此框架提供五种对话框的显示,并支持对话框的扩展,目的是为了提供对话框的统一管理,并提供对话框显示的公共接口。...

    android-dialog 此框架提供七种对话框的显示,并支持对话框的扩展,目的是为了提供对话框的统一管理,并提供对话框显示的公共接口. LoadingDialog:正在加载对话框 MessageD ...

最新文章

  1. android studio不自动生成r.java_Android 添加构建依赖
  2. python3字典详解_python3中字典详解
  3. 【Python】Jupyter notebook
  4. Loader之二:CursorLoader基本实例
  5. percona-toolkit--pt-table-checksum
  6. 字符串替换(C++)
  7. Supervisord管理
  8. 外媒:日本和芬兰将合作开发6G技术 诺基亚将参与其中
  9. 世界上最狠最毒的动物是什么?
  10. Linux 命令(76)—— kill 命令
  11. dnf时装补丁教程_dnf时装补丁怎么用?DNF时装补丁教程
  12. html导航栏分割线如何,网页导航栏用图片做的分割线,第一个分割线怎么取消...
  13. NUC980 PWM
  14. 2021年美容师(初级)考试内容及美容师(初级)模拟考试题
  15. ldo和dcdc功耗_电路设计中LDO与DC/DC的选择问题(LDO篇)
  16. b站路飞学城python课梨视频项目代码
  17. NLTK常用操作和语料库
  18. 【数据结构】十进制转化为二进制
  19. 网站被服务器禁,又一次腾讯云服务器网站被封禁 设备存在违规信息被限制访问 - 小俊学习网...
  20. Windows服务器双网卡绑定的方法(HP/Broadcom网卡)

热门文章

  1. 海康AI开放平台初体验
  2. linux shell awk 语法
  3. c语言基础 —— 程序结构
  4. 优先队列之堆排序((二)升级版)
  5. 全国计算机应用基础统考成绩查询,2020年12月网络教育统考成绩查询时间及入口...
  6. GaussDB数据库基础函数介绍-上
  7. 云数据库CynosDB有哪些常见问题?
  8. 数据库系列(3):数据库管理系统的分类
  9. 基于Appfuse的Web应用快速开发
  10. 生信学习笔记:fastp质控处理生成的report结果解读