声明:此处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 :
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> map = parentElement.getExtensionElements();
List 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:
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> getConvertersToBpmnMap(){
return convertersToBpmnMap;
}
/**
* 获取bpmn组件解析map
* @return
*/
public static Map, Class> getConvertersToJsonMap(){
return convertersToJsonMap;
}
}
CustomBpmnXmlConverter:
import org.activiti.bpmn.converter.BpmnXMLConverter;
/**
* 自定义bpmn解析,用于xml转换成BPMN
*
*/
public class CustomBpmnXmlConverter extends BpmnXMLConverter {
static {
// 添加自定义用户节点xml解析器
addConverter(new CustomUserTaskXmlConverter());
}
}
CustomUserTaskJsonConverter:用户节点自定义扩展属性解析(xml与json互转)
用到的常量为自定义属性名
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> map = userTask.getExtensionElements();
for(String key : map.keySet()){
List 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 shapeMap) {
FlowElement flowElement = super.convertJsonToElement(elementNode, modelNode, shapeMap);
//解析
UserTask userTask = (UserTask) flowElement;
List 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> convertersToBpmnMap,
Map, Class> convertersToJsonMap) {
fillJsonTypes(convertersToBpmnMap);
fillBpmnTypes(convertersToJsonMap);
}
public static void fillJsonTypes(Map> convertersToBpmnMap) {
convertersToBpmnMap.put(STENCIL_TASK_USER, CustomUserTaskJsonConverter.class);
}
public static void fillBpmnTypes(Map, Class> convertersToJsonMap) {
convertersToJsonMap.put(UserTask.class, CustomUserTaskJsonConverter.class);
}
/**
* 处理自定义属性
*
* @param cpList 自定义属性列表
* @param elementNode 任务节点
* @param key 自定义属性key
*/
private void handleCustomProperties(List 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
用到的常量为自定义属性名
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:
重点在于下面这句:
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:常量表
/**
* 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
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;
}