MarkDown版本:https://www.jianshu.com/p/c1fb9324b476
flowable每个节点自带的属性是有限的,而在实际业务中可能会遇到一些比较适合配置到各个节点属性,但是自带属性里面又没有的,所以这个时候我们就需要自己自定义属性了,这里主要记录下自己处理的过程,方便以后遇到该问题好查阅。
修改前端
(1).修改文件:stencilset_bpmn.json
(2).新增2个属性:
(3).把新增的属性添加到UserTask 节点
前端修改之后页面的效果:
这样配好之后我们去下载xml的时候会发现没有这两个新增的属性,这个时候在流程实例流转的时候也是获取不到新增属性的值的。
是因为flowable并没有支持自定义属性的存储,所以这个时候就要自己对自定义属性进行解析了。
后端修改
(1).我们可以从页面找到下载的请求路径。可以看到是app/rest/models/**
因为是源码我这边为了尽量不改他的源码,所以自己修改了请求地址,自己写了下载的实现。
修改url-config跳转地址:app/rest/models/** 改成 XX/app/rest/models/**
(2).新建ModelController 继承 AbstractModelBpmnResource:
@RestController
@RequestMapping("/XX/app")
//@Transactional
public class ModelControllerextends AbstractModelBpmnResource {
private static final Logger LOGGER = LoggerFactory.getLogger(ModelController.class);
@Autowired
protected XXModelServiceImpl xxModelService;
/**
* GET /rest/models/{modelId}/bpmn20 -> Get BPMN 2.0 xml
*/
@RequestMapping(value ="/rest/models/{processModelId}/bpmn20", method = RequestMethod.GET)
public void getProcessModelBpmn20Xml(HttpServletResponse response, @PathVariable String processModelId)throws IOException {
LOGGER.info("开始下载xml文件1");
if (processModelId ==null) {
throw new BadRequestException("No process model id provided");
}
Model model = xxModelService.getModel(processModelId);
generateBpmn20Xml(response, model);
}
protected void generateBpmn20Xml(HttpServletResponse response, AbstractModel model) {
String name = model.getName().replaceAll(" ", "_") +".bpmn20.xml";
String encodedName =null;
try {
encodedName ="UTF-8''" + URLEncoder.encode(name, "UTF-8");
}catch (Exception e) {
LOGGER.warn("Failed to encode name " + name);
}
String contentDispositionValue ="attachment; filename=" + name;
if (encodedName !=null) {
contentDispositionValue +="; filename*=" + encodedName;
}
response.setHeader("Content-Disposition", contentDispositionValue);
if (model.getModelEditorJson() !=null) {
try {
ServletOutputStream servletOutputStream = response.getOutputStream();
response.setContentType("application/xml");
BpmnModel bpmnModel = xxModelService.getBpmnModel(model);
byte[] xmlBytes = xxModelService.getBpmnXML(bpmnModel);
BufferedInputStream in =new BufferedInputStream(new ByteArrayInputStream(xmlBytes));
byte[] buffer =new byte[8096];
while (true) {
int count = in.read(buffer);
if (count == -1) {
break;
}
servletOutputStream.write(buffer, 0, count);
}
// Flush and close stream
servletOutputStream.flush();
servletOutputStream.close();
}catch (BaseModelerRestException e) {
throw e;
}catch (Exception e) {
LOGGER.error("Could not generate BPMN 2.0 XML", e);
throw new InternalServerErrorException("Could not generate BPMN 2.0 xml");
}
}
}
}
(3).新建XXModelServiceImpl 继承 ModelServiceImpl
(4).新建XXBpmnJsonConverter 继承 BpmnJsonConverter
(5).新建自定义userTaskjson解析器XXCustomizeUserTaskJsonConverter 继承UserTaskJsonConverter```public class XXCustomizeUserTaskJsonConverterextends UserTaskJsonConverter {
private static final Logger LOGGER = LoggerFactory.getLogger(XXCustomizeUserTaskJsonConverterextends.class);
private static final String RETURN_TO_THE_SPECIFIED_NODE ="returntothespecifiednode";
private static final String RETURN_TO_THE_SPECIFIED_NODE_KEY ="returnToTheSpecifiedNode";
private static final String APPROVAL_OPERATION ="approvaloperation";
private static final String APPROVAL_OPERATION_KEY ="approvalOperation";
public static void fillBpmnTypes(
Map, Class> convertersToJsonMap) {
convertersToJsonMap.put(UserTask.class, XXCustomizeUserTaskJsonConverter.class);
}
@Override
protected FlowElement convertJsonToElement(JsonNode elementNode, JsonNode modelNode,
Map shapeMap) {
FlowElement flowElement =super.convertJsonToElement(elementNode, modelNode, shapeMap);
LOGGER.info("进入自定义属性解析");
if(flowElementinstanceof UserTask){
ObjectMapper objectMapper =new ObjectMapper();
UserTask userTask = (UserTask) flowElement;
try {
LOGGER.info("节点:" + objectMapper.writeValueAsString(userTask));
}catch (JsonProcessingException e) {
LOGGER.error("节点序列化异常.");
}
String returnToTheSpecifiedNode = getPropertyValueAsString(RETURN_TO_THE_SPECIFIED_NODE, elementNode);
LOGGER.info("新增自定义属性[" + RETURN_TO_THE_SPECIFIED_NODE +"]=" + returnToTheSpecifiedNode);
String approvalOperation = getPropertyValueAsString(APPROVAL_OPERATION, elementNode);
LOGGER.info("新增自定义属性[" + APPROVAL_OPERATION +"]=" + approvalOperation);
Map> atts =new HashMap>();
ExtensionAttribute ea1 = ExtensionAttributeUtils.generate(RETURN_TO_THE_SPECIFIED_NODE_KEY,returnToTheSpecifiedNode);
ExtensionAttribute ea2 = ExtensionAttributeUtils.generate(APPROVAL_OPERATION_KEY,approvalOperation);
atts.put("XX-FLOWABLE-EXT ",Arrays.asList(ea1,ea2));
flowElement.setAttributes(atts);
}
return flowElement;
}
}
```
修改代码重新部署之后再下载xml:
可以看到新增属性再xml里面已经保存成功了。
发起一支流程,去实例中看看能不能取到该新增属性的值。