flowable自定义属性

MarkDown版本:https://www.jianshu.com/p/c1fb9324b476

flowable每个节点自带的属性是有限的,而在实际业务中可能会遇到一些比较适合配置到各个节点属性,但是自带属性里面又没有的,所以这个时候我们就需要自己自定义属性了,这里主要记录下自己处理的过程,方便以后遇到该问题好查阅。

修改前端

     (1).修改文件:stencilset_bpmn.json

     (2).新增2个属性:

flowable自定义属性_第1张图片
新增属性

     (3).把新增的属性添加到UserTask 节点

flowable自定义属性_第2张图片
属性添加到UserTask节点

    前端修改之后页面的效果:

flowable自定义属性_第3张图片
新增自定义属性的效果

这样配好之后我们去下载xml的时候会发现没有这两个新增的属性,这个时候在流程实例流转的时候也是获取不到新增属性的值的。

flowable自定义属性_第4张图片
前端修改之后xml并没有新增的属性

是因为flowable并没有支持自定义属性的存储,所以这个时候就要自己对自定义属性进行解析了。

后端修改

 (1).我们可以从页面找到下载的请求路径。可以看到是app/rest/models/**


flowable自定义属性_第5张图片
xml下载的请求路径

因为是源码我这边为了尽量不改他的源码,所以自己修改了请求地址,自己写了下载的实现。

修改url-config跳转地址:app/rest/models/** 改成  XX/app/rest/models/**

修改xml下载请求路径

(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


flowable自定义属性_第6张图片

(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:

flowable自定义属性_第7张图片
新增属性存储到了xml

可以看到新增属性再xml里面已经保存成功了。



发起一支流程,去实例中看看能不能取到该新增属性的值。


flowable自定义属性_第8张图片
实例流程中能获取到新增属性的值

你可能感兴趣的:(flowable自定义属性)