actitivi自定义属性(二)

声明:此处activiti版本为6.0

此文章介绍后端自定义属性解析,前端添加自定义属性方法连接:activiti自定义属性(一)_ruoyi activiti自定义标题-CSDN博客

1、涉及到的类如下:

简介:DefaultXmlParser :xml自定义属性解析类 :实现解析指定节点下扩展字段xml节点

CustomBpmnJsonConverter:用于转换BPMN与JSON供activiti解析界面属性并应用,在ActivitiConfig中引入使用

CustomBpmnXmlConverter:用于xml与BPMN转换

CustomUserTaskJsonConverter:用户节点自定义扩展属性解析(xml与json互转)

CustomUserTaskXmlConverter:用户节点自定义扩展属性解析xml

ActivitiConfig:springboot整合activiti配置类

代码如下:

DefaultXmlParser :

java 复制代码
import org.activiti.bpmn.converter.child.BaseChildElementParser;
import org.activiti.bpmn.model.*;

import javax.xml.stream.XMLStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * xml自定义属性解析类 :实现解析指定节点下扩展字段xml节点
 *
 */
public class DefaultXmlParser extends BaseChildElementParser {

    //元素名称
    private String elementName;

    public DefaultXmlParser() {
    }

    public DefaultXmlParser(String elementName) {
        this.elementName = elementName;
    }

    public String getElementName() {
        return elementName;
    }

    /**
     * 解析指定节点下扩展字段xml节点
     * @param xtr               xml字节流读取器
     * @param parentElement     父节点对象
     * @param model             流程图模型对象
     * @throws Exception
     */
    public void parseChildElement(XMLStreamReader xtr, BaseElement parentElement, BpmnModel model) throws Exception {
        Map<String, List<ExtensionElement>> map = parentElement.getExtensionElements();
        List<ExtensionElement> extensionElementList = new ArrayList<>();
        ExtensionElement extensionElement = new ExtensionElement();
        extensionElement.setName(getElementName());
        extensionElement.setElementText(xtr.getElementText());
        extensionElement.setNamespacePrefix("activiti");
        extensionElement.setNamespace("http://activiti.org/bpmn");
        extensionElementList.add(extensionElement);
        map.put(getElementName(), extensionElementList);

    }
}

CustomBpmnJsonConverter:

java 复制代码
import org.activiti.bpmn.model.BaseElement;
import org.activiti.editor.language.json.converter.BaseBpmnJsonConverter;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;

import java.util.Map;

/**
 * 自定义bpmn解析,用于转换BPMN与JSON供activiti解析界面属性并应用
 *
 */
public class CustomBpmnJsonConverter extends BpmnJsonConverter {

    /**
     * 获取bpmn组件解析map
     * @return
     */
    public static Map<String,Class<? extends BaseBpmnJsonConverter>> getConvertersToBpmnMap(){
        return convertersToBpmnMap;
    }

    /**
     * 获取bpmn组件解析map
     * @return
     */
    public static Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>>  getConvertersToJsonMap(){
        return convertersToJsonMap;
    }

}

CustomBpmnXmlConverter:

java 复制代码
import org.activiti.bpmn.converter.BpmnXMLConverter;

/**
 * 自定义bpmn解析,用于xml转换成BPMN
 *
 */
public class CustomBpmnXmlConverter extends BpmnXMLConverter {

    static {
        // 添加自定义用户节点xml解析器
        addConverter(new CustomUserTaskXmlConverter());
    }
}

CustomUserTaskJsonConverter:用户节点自定义扩展属性解析(xml与json互转)

用到的常量为自定义属性名

java 复制代码
import com.self.common.constant.activiti.ActivitiNodeConstant;
import com.self.common.utils.StringUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.model.*;
import org.activiti.editor.language.json.converter.BaseBpmnJsonConverter;
import org.activiti.editor.language.json.converter.UserTaskJsonConverter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 用户节点自定义扩展属性解析(xml与json互转)
 */
public class CustomUserTaskJsonConverter extends UserTaskJsonConverter {

    /**
     * xml => json
     * 将 xml格式的模型数据解析出来放入到节点的json自定义扩展属性中
     *
     * @param propertiesNode
     * @param baseElement
     */
    @Override
    protected void convertElementToJson(ObjectNode propertiesNode, BaseElement baseElement) {
        super.convertElementToJson(propertiesNode, baseElement);
        //获取扩展属性并进行设置
        UserTask userTask = (UserTask) baseElement;

        Map<String, List<ExtensionElement>> map = userTask.getExtensionElements();
        for(String key : map.keySet()){
            List<ExtensionElement> extensionElementList = map.get(key);
            if (extensionElementList != null && extensionElementList.size() > 0) {
                propertiesNode.put(extensionElementList.get(0).getName(), extensionElementList.get(0).getElementText());
            }
        }
    }

    /**
     * json => xml
     * 将 json格式的模型数据解析出来放入到节点的自定义扩展属性中
     *
     * @param elementNode
     * @param modelNode
     * @param shapeMap
     * @return
     */
    @Override
    protected FlowElement convertJsonToElement(JsonNode elementNode, JsonNode modelNode, Map<String, JsonNode> shapeMap) {
        FlowElement flowElement = super.convertJsonToElement(elementNode, modelNode, shapeMap);
        //解析
        UserTask userTask = (UserTask) flowElement;
        List<CustomProperty> cpList = new ArrayList<>();
        //是否为并行节点,常量为自定义属性名
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_PARALLEL);
        //是否可以AA跳
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_SKIP_TASK);
        //节点审批人为空是否跳过
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_APPROVAL_NULL_SKIP_TASK);
        //跳过节点时意见
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_SKIP_TASK_OPINION);
        //是否可以修改表单
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_ACTMODIFY_FROM);
        //附件是否必填
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_FILE_REQUIRED);
        //是否可以查看流转记录
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_APPROVAL_RECORD);
        //是否可配置审批记录查看权限
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_RECORD_PERMISSIONS);
        //抄送用户
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_CC_USERS);
        //是否显示流程图
        handleCustomProperties(cpList, elementNode, ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_APPROVAL_PNG);
        userTask.setCustomProperties(cpList);
        return userTask;
    }

    public static void fillTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap,
                                 Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {

        fillJsonTypes(convertersToBpmnMap);
        fillBpmnTypes(convertersToJsonMap);
    }

    public static void fillJsonTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap) {
        convertersToBpmnMap.put(STENCIL_TASK_USER, CustomUserTaskJsonConverter.class);
    }

    public static void fillBpmnTypes(Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {
        convertersToJsonMap.put(UserTask.class, CustomUserTaskJsonConverter.class);
    }

    /**
     * 处理自定义属性
     *
     * @param cpList      自定义属性列表
     * @param elementNode 任务节点
     * @param key         自定义属性key
     */
    private void handleCustomProperties(List<CustomProperty> cpList, JsonNode elementNode, String key) {
        String value = getPropertyValueAsString(key, elementNode);
        if (StringUtils.isNotBlank(value)) {
            CustomProperty cp = new CustomProperty();
            cp.setName(key);
            cp.setSimpleValue(value);
            cpList.add(cp);
        }
    }

}

CustomUserTaskXmlConverter:用户节点自定义扩展属性解析xml

用到的常量为自定义属性名

java 复制代码
import com.self.activiti.config.extension.DefaultXmlParser;
import com.self.common.constant.activiti.ActivitiNodeConstant;
import org.activiti.bpmn.converter.UserTaskXMLConverter;

/**
 * 用户节点自定义扩展属性解析xml
 */
public class CustomUserTaskXmlConverter extends UserTaskXMLConverter {

    public CustomUserTaskXmlConverter() {
        super();
        //是否为并行节点
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_PARALLEL, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_PARALLEL));
        //是否可以AA跳
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_SKIP_TASK, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_SKIP_TASK));
        //节点审批人为空是否跳过
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_APPROVAL_NULL_SKIP_TASK, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_APPROVAL_NULL_SKIP_TASK));
        //跳过节点时意见
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_SKIP_TASK_OPINION, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_SKIP_TASK_OPINION));
        //是否可以修改表单
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACTMODIFY_FROM, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACTMODIFY_FROM));
        //附件是否必填
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_FILE_REQUIRED, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_FILE_REQUIRED));
        //是否可以查看流转记录
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_APPROVAL_RECORD, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_APPROVAL_RECORD));
        //是否可配置审批记录查看权限
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_RECORD_PERMISSIONS, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_RECORD_PERMISSIONS));
        //抄送用户
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_CC_USERS, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_CC_USERS));
        //是否显示流程图
        childParserMap.put(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_APPROVAL_PNG, new DefaultXmlParser(ActivitiNodeConstant.CUSTOM_PROPERTIES_ACT_APPROVAL_PNG));

    }
}

ActivitiConfig:

重点在于下面这句:

java 复制代码
import com.self.activiti.id.MyIdGenerator;
import org.activiti.engine.*;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

/**
 * acitiviti配置类
 */
@Configuration
public class ActivitiConfig  {
    @Autowired
    private DataSource dataSource;
    @Autowired
    private PlatformTransactionManager transactionManager;

    //流程配置,与spring整合采用SpringProcessEngineConfiguration这个实现
    @Bean
    public SpringProcessEngineConfiguration processEngineConfiguration(){
        SpringProcessEngineConfiguration processEngineConfiguration = new SpringProcessEngineConfiguration();
        processEngineConfiguration.setDataSource(dataSource);
        processEngineConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfigurationImpl.DB_SCHEMA_UPDATE_TRUE);
        processEngineConfiguration.setDatabaseType(ProcessEngineConfigurationImpl.DATABASE_TYPE_MYSQL);
        processEngineConfiguration.setIdGenerator(new MyIdGenerator());
        processEngineConfiguration.setTransactionManager(transactionManager);
        processEngineConfiguration.setJobManager(new MyJobManager());//自定义任务管理

        // 将自定义用户任务组件bpmn解析替换activiti中用户任务组件默认解析
        CustomUserTaskJsonConverter.fillTypes(CustomBpmnJsonConverter.getConvertersToBpmnMap(), CustomBpmnJsonConverter.getConvertersToJsonMap());

//        processEngineConfiguration.setJobExecutorActivate(true);//JobExecutor是管理几个线程计时器的组成部分,JobExecutor对多线程的处理较为笨重缓慢
//        processEngineConfiguration.setAsyncExecutorEnabled(true);//定义为true,使用AsyncExecutor代替默认的JobExecutor;
        processEngineConfiguration.setAsyncExecutorActivate(true);//定义为true,工作流引擎在启动时就建立启动AsyncExecutor线程
        //流程图字体
        processEngineConfiguration.setActivityFontName("宋体");
        processEngineConfiguration.setAnnotationFontName("宋体");
        processEngineConfiguration.setLabelFontName("宋体");

        return processEngineConfiguration;
    }

    //流程引擎,与spring整合使用factoryBean
    @Bean
    public ProcessEngineFactoryBean processEngine(ProcessEngineConfiguration processEngineConfiguration){
        ProcessEngineFactoryBean processEngineFactoryBean = new ProcessEngineFactoryBean();
        processEngineFactoryBean.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);
        ((ProcessEngineConfigurationImpl) processEngineConfiguration).setIdGenerator(new MyIdGenerator());
        return processEngineFactoryBean;
    }
    //八大接口
    @Bean
    public RepositoryService repositoryService(ProcessEngine processEngine){
        return processEngine.getRepositoryService();
    }

    @Bean
    public RuntimeService runtimeService(ProcessEngine processEngine){
        return processEngine.getRuntimeService();
    }

    @Bean
    public TaskService taskService(ProcessEngine processEngine){
        return processEngine.getTaskService();
    }

    @Bean
    public HistoryService historyService(ProcessEngine processEngine){
        return processEngine.getHistoryService();
    }

    @Bean
    public FormService formService(ProcessEngine processEngine){
        return processEngine.getFormService();
    }

    @Bean
    public IdentityService identityService(ProcessEngine processEngine){
        return processEngine.getIdentityService();
    }

    @Bean
    public ManagementService managementService(ProcessEngine processEngine){
        return processEngine.getManagementService();
    }

    @Bean
    public DynamicBpmnService dynamicBpmnService(ProcessEngine processEngine){
        return processEngine.getDynamicBpmnService();
    }

}

ActivitiNodeConstant:常量表

java 复制代码
/**
 * activiti节点类型常量表
 *
 */
public class ActivitiNodeConstant {

    //会签节点名称后缀
    public static final String NODE_NAME_COUNTERSIGN_SUFFIX = "-会签";


    //流程节点类型 -- 互斥网关
    public static final String NODE_NAME_EXCLUSIVE_GATEWAY = "exclusiveGateway";
    //流程节点类型 -- 并行网关
    public static final String NODE_NAME_PARALLEL_GATEWAY = "parallelGateway";
   //流程节点类型 -- 包容网关
    public static final String NODE_NAME_INCLUSIVE_GATEWAY = "inclusiveGateway";
    //流程节点类型 -- 开始事件
    public static final String NODE_NAME_START_EVENT = "startEvent";
    //流程节点类型 -- 结束事件
    public static final String NODE_NAME_END_EVENT = "endEvent";
    //流程节点类型 -- 边界事件
    public static final String NODE_NAME_BOUNDARY_EVENT = "boundaryEvent";
    //流程节点类型 -- 用户任务
    public static final String NODE_NAME_USER_TASK = "userTask";
    //流程节点类型 -- 服务任务
    public static final String NODE_NAME_SERVICE_TASK = "serviceTask";

    //节点自定义属性 -- 是否为并行节点
    public static final String CUSTOM_PROPERTIES_PARALLEL = "isparallel";
    //节点自定义属性 -- 是否可以AA跳
    public static final String CUSTOM_PROPERTIES_SKIP_TASK = "skiptask";
    //节点自定义属性 -- 节点审批人为空是否跳过
    public static final String CUSTOM_PROPERTIES_APPROVAL_NULL_SKIP_TASK = "approvalnullskiptask";
    //节点自定义属性 -- 跳过节点时意见
    public static final String CUSTOM_PROPERTIES_SKIP_TASK_OPINION = "skiptaskopinion";
    //节点自定义属性 -- 是否可以修改表单
    public static final String CUSTOM_PROPERTIES_ACTMODIFY_FROM = "actmodifyfrom";
    //节点自定义属性 -- 附件是否必填
    public static final String CUSTOM_PROPERTIES_FILE_REQUIRED = "filerequired";
    //节点自定义属性 -- 是否可以查看流转记录
    public static final String CUSTOM_PROPERTIES_ACT_APPROVAL_RECORD = "actapprovalrecord";
    //节点自定义属性 -- 是否可配置审批记录查看权限
    public static final String CUSTOM_PROPERTIES_ACT_RECORD_PERMISSIONS = "actrecordpermissions";
    //节点自定义属性 -- 抄送用户
    public static final String CUSTOM_PROPERTIES_CC_USERS = "ccusers";
    //节点自定义属性 -- 是否显示流程图
    public static final String CUSTOM_PROPERTIES_ACT_APPROVAL_PNG = "actapprovalpng";



}

使用方法:

1、读取xml文件,转为bpmnModel

java 复制代码
private BpmnModel inputStream2Xml(InputStream inputStream) throws Exception {
        //读取xml文件
        XMLInputFactory factory = XMLInputFactory.newInstance();
        XMLStreamReader reader = factory.createXMLStreamReader(new InputStreamReader(inputStream, "UTF-8"));
        BpmnModel bpmnModel = new CustomBpmnXmlConverter().convertToBpmnModel(reader);
        // bpmnModel转json
        BpmnJsonConverter converter = new BpmnJsonConverter();
        converter.convertToJson(bpmnModel);

        return bpmnModel;
    }
相关推荐
minDuck1 分钟前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js
为将者,自当识天晓地。20 分钟前
c++多线程
java·开发语言
daqinzl28 分钟前
java获取机器ip、mac
java·mac·ip
激流丶44 分钟前
【Kafka 实战】如何解决Kafka Topic数量过多带来的性能问题?
java·大数据·kafka·topic
Themberfue1 小时前
Java多线程详解⑤(全程干货!!!)线程安全问题 || 锁 || synchronized
java·开发语言·线程·多线程·synchronized·
让学习成为一种生活方式1 小时前
R包下载太慢安装中止的解决策略-R语言003
java·数据库·r语言
晨曦_子画1 小时前
编程语言之战:AI 之后的 Kotlin 与 Java
android·java·开发语言·人工智能·kotlin
南宫生2 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
Heavydrink2 小时前
HTTP动词与状态码
java
ktkiko112 小时前
Java中的远程方法调用——RPC详解
java·开发语言·rpc