springboot集成activiti model后模型编辑

接本专题上一篇

问题描述

集成后新增模型可以直接访问“modeler.html”进行编辑保存。但是在修改已保存模型的时候怎么也没法初始化,带上modelId参数也没用。

解决方法

activiti model 编辑需要提供editor方法,再返回 modeler.html,代码如下,要注意这里不是REST接口,需要使用到模板框架,我这里使用了freemarker将页面返回。

/**
 * @author czj
 */
@Controller
public class ActivitiPageController {

    /**
     * 主要为异步调用而写,若访问地址为editor则页面载入后会
     * 同时调用/model/{modelId}/json 对模型进行初始化
     *
     * @return
     */
    @RequestMapping("editor")
    public String editor() {
        return "modeler.html";
    }
}

当页面载入后,会再次调用/service/model/{modelId}/json 获取模板信息,完整controller如下。

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

import static org.activiti.editor.constants.ModelDataJsonConstants.*;

/**
 * 调出流程图绘制界面
 */
@RestController
public class ActivitiModelController {

    private static final Logger LOGGER = LoggerFactory.getLogger(ActivitiModelController.class);

    @Resource
    private RepositoryService repositoryService;
    /** 定义流程引擎 */
    @Resource
    private ProcessEngine processEngine;
    @Resource
    private ObjectMapper objectMapper;
    /** 模型的版本 */
    private final static Integer MODEL_REVISION = 1;
    /** modeler.html页面地址 */
    private final static String ACTIVITI_REDIRECT_MODELER_INDEX = "/modeler.html?modelId=";
    /** 默认的空间值 */
    private final static String ACTIVITI_NAMESPACE_VALUE = "http://b3mn.org/stencilset/bpmn2.0#";
    /** 默认ID值 */
    private final static String ACTIVITI_ID_VALUE = "canvas";

    /**
     * 新建一个模型
     *
     * @param response
     * @throws IOException
     */
    @RequestMapping("/activiti-ui.html")
    public void newModel(HttpServletResponse response) throws IOException {
        RepositoryService repositoryService = processEngine.getRepositoryService();

        // 初始化空的流程资源模型,填充信息并持久化模型
        Model model = repositoryService.newModel();
        String uuid = UUID.randomUUID().toString();
        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put(MODEL_NAME, uuid);
        modelNode.put(MODEL_DESCRIPTION, "");
        modelNode.put(ModelDataJsonConstants.MODEL_REVISION, MODEL_REVISION);
        model.setName(uuid);
        model.setKey(uuid);
        model.setMetaInfo(modelNode.toString());
        repositoryService.saveModel(model);

        // 将 editorNode  数据填充到模型中, 并做页面的重定向
        ObjectNode editorNode = objectMapper.createObjectNode();
        editorNode.put("id", ACTIVITI_ID_VALUE);
        editorNode.put("resourceId", ACTIVITI_ID_VALUE);
        ObjectNode stencilSetNode = objectMapper.createObjectNode();
        stencilSetNode.put("namespace", ACTIVITI_NAMESPACE_VALUE);
        editorNode.set("stencilset", stencilSetNode);
        repositoryService.addModelEditorSource(model.getId(), editorNode.toString().getBytes(StandardCharsets.UTF_8));
        response.sendRedirect(ACTIVITI_REDIRECT_MODELER_INDEX + model.getId());
    }

    /**
     * 保存模型
     *
     * @param modelId
     * @param name
     * @param description
     * @param json_xml
     * @param svg_xml
     */
    @RequestMapping(value = "/service/model/{modelId}/save", method = RequestMethod.PUT)
    @ResponseStatus(value = HttpStatus.OK)
    public void saveModel(@PathVariable 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(StandardCharsets.UTF_8));

            InputStream svgStream = new ByteArrayInputStream(svg_xml.getBytes(StandardCharsets.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) {
            LOGGER.error("Error saving model", e);
            throw new ActivitiException("Error saving model", e);
        }
    }

    /**
     * 获取模板编辑信息
     *
     * @param modelId
     * @return
     */
    @RequestMapping(value = "/service/model/{modelId}/json", method = RequestMethod.GET, produces = "application/json")
    public ObjectNode getEditorJson(@PathVariable 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()), StandardCharsets.UTF_8));
                modelNode.put("model", editorJsonNode);
            } catch (Exception e) {
                LOGGER.error("获取模板JSON失败", e);
                throw new ActivitiException("获取模板JSON失败", e);
            }
        }
        return modelNode;
    }

    /**
     * 加载模板集配置
     *
     * @return
     */
    @RequestMapping(value = "/service/editor/stencilset", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    public @ResponseBody
    String getStencilset() {
        try {
            InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("static/stencilset.json");
            return IOUtils.toString(stencilsetStream, "utf-8");
        } catch (Exception e) {
            throw new ActivitiException("加载模板集配置失败", e);
        }
    }
}

可能你的地址不一样,修改对应前端调用地址配置文件在 editor-app\app-cfg.js


'use strict';

var ACTIVITI = ACTIVITI || {};

ACTIVITI.CONFIG = {
// 我是配置的以service开头,不建议使用activiti开头,防止和activiti提供的rest接口冲突。
    'contextRoot' : '/service',
};

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容