boot-admin整合flowable官方editor-app源码进行BPMN2-0建模(续)
boot-admin整合flowable官方editor-app源码进行BPMN2-0建模(续)
书接上回
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
@Slf4j
public 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<Model> list = repositoryService.createModelQuery().listPage(offset
, queryVO.getPageSize());
int total = (int) repositoryService.createModelQuery().count();
Page<Model> page = new Page<>();
page.setRecords(list);
page.setTotal(total);
return ResultDTO.success(page);
}
读取模型数据
controller:
@RequestMapping("/api/workflow/auth/activiti")
@RestController
@Slf4j
public 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
@Slf4j
public 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
@Slf4j
public 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
@Slf4j
public 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 运行效果如下图所示:

boot-admin整合flowable官方editor-app源码进行BPMN2-0建模(续)的更多相关文章
- SpringBoot2.x整合Prometheus+Grafana【附源码+视频】
图文并茂,新手入门教程,建议收藏 SpringBoot2.x整合Prometheus+Grafana[附源码+视频] 附源码+视频 目录 工程简介 简介 Prometheus grafana Spri ...
- 基于Android开发的天气预报app(源码下载)
原文:基于Android开发的天气预报app(源码下载) 基于AndroidStudio环境开发的天气app -系统总体介绍:本天气app使用AndroidStudio这个IDE工具在Windows1 ...
- 方维 o2o app源码出售
方维 o2o app源码出售 方维o2oapp源码出售 1.本人官方5万购买,现把方维o2o app 源码低价出售: 2.包括网站源码本地搭建包成功提供指导 3.包括网站说明文档,不包含app说明文档 ...
- android 在线升级借助开源中国App源码
android 在线升级借助开源中国App源码 http://www.cnblogs.com/luomingui/p/3949429.html android 在线升级借助开源中国App源码分析如下: ...
- APP源码集中打包大放送!十一个千万级别APP源码随意处置!
小伙伴们还在一个一个苦苦寻找各类APP源码吗?此贴集中打包最常用APP的源码,你想得到的APP,这里都有! 想做商城?这里有天猫! 想做同城服务?这里有大众点评! 想做外卖?这里有饿了么! 想做视频? ...
- iOS高仿app源码:纯代码打造高仿优质《内涵段子》
iOS高仿app源码:纯代码打造高仿优质<内涵段子>收藏下来 字数1950 阅读4999 评论173 喜欢133 Github 地址 https://github.com/Charlesy ...
- android动画源码合集、动态主题框架、社交app源码等
Android精选源码 仿MIUI果冻视图-BouncingJellyView 一个快速易用的动态主题框架 android动画效果集合源码 android使用Kotlin开发的Dribbb ...
- 通过官方API结合源码,如何分析程序流程
通过官方API结合源码,如何分析程序流程通过官方API找到我们关注的API的某个方法,然后把整个流程执行起来,然后在idea中,把我们关注的方法打上断点,然后通过Step Out,从内向外一层一层分析 ...
- 导入android源码中的APP源码到eclipse
导入android源码中的APP源码到eclipse 一般最简单的办法就是创建新的android工程,选择create project from existing source选项,直接导入源码就OK ...
- 下载Google官方/CM Android源码自己主动又一次開始的Shell脚本
国内因为某种原因,下载CM或Google官方的Android源码总easy中断.总看着机器.一中断就又一次运行repo sync还太麻烦,所以我特意编写了一段shell脚本(download.sh). ...
随机推荐
- IEEE会议论文投稿系统问题之一:WinEdt编译生成DVI文件的方法
问题描述:如何将tex文件正确编译为dvi文件,以正常使用IEEE投稿系统? 方法: 1.打开WinEdt中的命令行: 2.使用latex TexFileName编译tex生成aux文件和dvi文件: ...
- Using Semaphores in Delphi, Part 2: The Connection Pool
Abstract: Semaphores are used to coordinate multiple threads and processes. That semaphores provide ...
- ASP.NET利用JQuery实现AJAX(前台脚本代码)调用后台静态方法
前台页面的script代码 PS: 如果不需要参数的话,就把data那一行删除 $(function () { //AJAX同步后台 var orderid = parseInt($(this).pa ...
- This class is not trusted to be serialized as ObjectMessage payload.ActiveMQ序列化设置
引子 ObjectMessage引入的生产者和消费者之间的类路径耦合,ActiveMQ支持他们作为JMS规范的一部分. ObjectMessage对象依赖marshal/unmarshal进行java ...
- idea远程仓库无法更新导致的各种错误,jar包无法下载
直接把下面的配置替换成settings.xml中的内容 <?xml version="1.0" encoding="UTF-8"?> <set ...
- 【MSSQL】远程打开对象
opendatasource https://docs.microsoft.com/zh-cn/sql/t-sql/functions/opendatasource-transact-sql?view ...
- (3)这是一个简单的html页面,请保持为字符串,完成后面的计算要求。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Java 比较两个对象的不同之处(old, new) 包含 bean 对象下的 list, Map , bean 的细节
Java 比较两个对象的不同之处(old, new) 包含 bean 对象下的 list, Map , bean 的细节 package com.icil.pinpal.test1; impor ...
- maven 多模块项目的测试覆盖率分析 - jacoco 聚合分析
前言 对于大多数 maven 多模块化工程,可以使用 Jacoco 这款工具,关于 Jacoco 这款工具,ChatGPT 对它的描述是这样的: JaCoCo(Java Code Coverage)是 ...
- 做bad apple第一步:超级好用的you-get下载各大网站音频!!!!
1 安装在cmd中输入pip3 install you-get 就行了 2 简单用法下载视频: 超级暴力,直接 you-get + "网站" 就没了,会下载到当前路径.我想下载到哪 ...