boot-admin整合flowable官方editor-app源码进行BPMN2-0建模(续)书接上回
项目源码仓库github项目源码仓库gitee
(资料图)
boot-admin是一款采用前后端分离模式、基于SpringCloud微服务架构的SaaS后台管理框架。系统内置基础管理、权限管理、运行管理、定义管理、代码生成器和办公管理6个功能模块,集成分布式事务Seata、工作流引擎Flowable、业务规则引擎Drools、后台作业调度框架Quartz等,技术栈包括Mybatis-plus、Redis、Nacos、Seata、Flowable、Drools、Quartz、SpringCloud、Springboot Admin Gateway、Liquibase、jwt、Openfeign、I18n等。
在上一篇博文中,已经介绍了 boot-admin 对 editor-app 前端代码的集成改造,接下来我们看看后端代码。
提供汉化资源json数据/** * 获取汉化资源 * @return */ @RequestMapping(value = "/editor/stencilset", method = RequestMethod.GET, produces = "application/json;charset=utf-8") public String getStencilset() { InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("stencilset.json"); try { return IOUtils.toString(stencilsetStream, "utf-8"); } catch (Exception e) { throw new FlowableException("Error while loading stencil set", e); } }
资源包stencilset.json需放在resources文夹下,这里提供下载:点击下载汉化包
分页获取模型列表controller:
@RequestMapping("/api/workflow/auth/activiti")@RestController@Slf4jpublic class ModelController extends BaseController { @Resource private FormValidator formValidator; @Autowired private MyModelService modelService; @PostMapping("/model/page") @ApiOperation("分页获取项目数据表列表") public ResultDTO getTablePage(@Valid @RequestBody ModelQueryVO queryVO, BindingResult bindingResult) throws Exception { if (bindingResult.hasErrors()) { return formValidator.generateMessage(bindingResult); } return modelService.getPage(queryVO); }}
service:
@Override public ResultDTO getPage(ModelQueryVO queryVO) throws Exception { int offset = (queryVO.getCurrentPage() - 1) * queryVO.getPageSize() + 0; List list = repositoryService.createModelQuery().listPage(offset , queryVO.getPageSize()); int total = (int) repositoryService.createModelQuery().count(); Page page = new Page<>(); page.setRecords(list); page.setTotal(total); return ResultDTO.success(page); }
读取模型数据controller:
@RequestMapping("/api/workflow/auth/activiti")@RestController@Slf4jpublic class ModelController extends BaseController { @Autowired private RepositoryService repositoryService; @Autowired private ObjectMapper objectMapper; /** * 获取用于编辑的模型JSON数据 * @param modelId 模型ID * @return */ @GetMapping(value = "/model/json") public ObjectNode getEditorJson(@RequestParam("modelId") String modelId) { ObjectNode modelNode = null; Model model = repositoryService.getModel(modelId); if (model != null) { try { if (StringUtils.isNotEmpty(model.getMetaInfo())) { modelNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo()); } else { modelNode = objectMapper.createObjectNode(); modelNode.put(MODEL_NAME, model.getName()); } modelNode.put(MODEL_ID, model.getId()); ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree( new String(repositoryService.getModelEditorSource(model.getId()), "utf-8")); modelNode.put("model", editorJsonNode); } catch (Exception e) { log.error("Error creating model JSON", e); throw new FlowableException("Error creating model JSON", e); } } return modelNode; }}
增加新模型controller:
@RequestMapping("/api/workflow/auth/activiti")@RestController@Slf4jpublic class ModelController extends BaseController { @Resource private FormValidator formValidator; @Autowired private MyModelService modelService; @PostMapping("/model/add") @ApiOperation("保存数据") public ResultDTO save(@Valid @RequestBody ModelDataVO dataVO, BindingResult bindingResult) throws Exception { if (bindingResult.hasErrors()) { return formValidator.generateMessage(bindingResult); } BaseUser baseUser = UserTool.getBaseUser(); return modelService.addNewModel(dataVO, baseUser); }}
service:
@Override public ResultDTO addNewModel(ModelDataVO dataVO, BaseUser baseUser) throws Exception { //初始化一个空模型 Model model = repositoryService.newModel(); //设置一些默认信息 String name = dataVO.getName(); String description = dataVO.getDescription(); int revision = 1; String key = dataVO.getKey(); ObjectNode modelNode = objectMapper.createObjectNode(); modelNode.put(MODEL_NAME, name); modelNode.put(MODEL_DESCRIPTION, description); modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision); model.setName(name); model.setKey(key); model.setMetaInfo(modelNode.toString()); repositoryService.saveModel(model); String id = model.getId(); //完善ModelEditorSource ObjectNode editorNode = objectMapper.createObjectNode(); editorNode.put("id", "canvas"); editorNode.put("resourceId", "canvas"); ObjectNode stencilSetNode = objectMapper.createObjectNode(); stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#"); editorNode.put("stencilset", stencilSetNode); repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8")); return ResultDTO.success(id); }
保存模型数据/** * 保存模型数据 * @param modelId * @param name * @param description * @param json_xml * @param svg_xml */ @RequestMapping(value = "/model/save", method = RequestMethod.PUT) @ResponseStatus(value = HttpStatus.OK) public void saveModel(@RequestParam("modelId") String modelId , String name, String description , String json_xml, String svg_xml) { try { Model model = repositoryService.getModel(modelId); ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo()); modelJson.put(MODEL_NAME, name); modelJson.put(MODEL_DESCRIPTION, description); model.setMetaInfo(modelJson.toString()); model.setName(name); repositoryService.saveModel(model); repositoryService.addModelEditorSource(model.getId(), json_xml.getBytes("utf-8")); InputStream svgStream = new ByteArrayInputStream(svg_xml.getBytes("utf-8")); TranscoderInput input = new TranscoderInput(svgStream); PNGTranscoder transcoder = new PNGTranscoder(); // Setup output ByteArrayOutputStream outStream = new ByteArrayOutputStream(); TranscoderOutput output = new TranscoderOutput(outStream); // Do the transformation transcoder.transcode(input, output); final byte[] result = outStream.toByteArray(); repositoryService.addModelEditorSourceExtra(model.getId(), result); outStream.close(); } catch (Exception e) { log.error("Error saving model", e); throw new FlowableException("Error saving model", e); } }
删除模型controller:
@RequestMapping("/api/workflow/auth/activiti")@RestController@Slf4jpublic class ModelController extends BaseController { @Resource private FormValidator formValidator; @Autowired private MyModelService modelService; @PostMapping("/model/del") @ApiOperation("删除数据") public ResultDTO del(@Valid @RequestBody GuidContainerVO guidContainerVO, BindingResult bindingResult) throws Exception { if (bindingResult.hasErrors()) { return formValidator.generateMessage(bindingResult); } return modelService.delete(guidContainerVO.getGuid()); } }
service:
@Override public ResultDTO delete(String guid) throws Exception { repositoryService.deleteModel(guid); return ResultDTO.success(); }
发布(部署)模型@RequestMapping("/api/workflow/auth/activiti")@RestController@Slf4jpublic class ModelController extends BaseController { @Resource private FormValidator formValidator; @Autowired private MyModelService modelService; @PostMapping("/model/deploy") public ResultDTO deploy(@Valid @RequestBody GuidContainerVO guidContainerVO, BindingResult bindingResult) throws Exception { if (bindingResult.hasErrors()) { return formValidator.generateMessage(bindingResult); } return modelService.deploy(guidContainerVO.getGuid()); }}
service:
@Override public ResultDTO deploy(String guid) throws Exception { /**获取模型 **/ Model modelData = repositoryService.getModel(guid); byte[] bytes = repositoryService.getModelEditorSource(modelData.getId()); if (bytes == null) { return ResultDTO.failureCustom("模型数据为空,请先设计流程并成功保存,再进行发布。"); } JsonNode modelNode = new ObjectMapper().readTree(bytes); BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode); if (model.getProcesses().size() == 0) { return ResultDTO.failureCustom("数据模型不符要求,请至少设计一条主线流程。"); } /** 设置名称 **/ if(StringUtils.isNotBlank(modelData.getCategory())) { model.setTargetNamespace(modelData.getCategory()); } byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model); /** 发布流程 .bpmn20.xml必需加 **/ String processName = modelData.getName() + ".bpmn20.xml"; Deployment deployment = repositoryService.createDeployment() .name(modelData.getName()) .category(modelData.getCategory()) .key(modelData.getKey()) .addString(processName, new String(bpmnBytes, "UTF-8")) .deploy(); modelData.setDeploymentId(deployment.getId()); repositoryService.saveModel(modelData); return ResultDTO.success(); }
总结:经过集成改造,boot-admin与flowable editor-app模型设计器实现紧密整合,不但实现了BPMN流程编辑、修改、发布等功能,还实现前端 携带jwt按权限访问后端资源。boot-admin 集成 flowable editor-app 运行效果如下图所示:
项目源码仓库github项目源码仓库gitee