Spring Boot2 + Activiti6 集成在线流程设计器 Activiti modoler(3)

3 篇文章 0 订阅
3 篇文章 0 订阅

前言

上篇文章介绍了如何在Spring Boot2集成activiti6

接下来,小编会一步一步的介绍如何集成在线设计器

Activiti Modoler 介绍

什么是 Activiti Modoler 呢,简单的说就是一个在线画流程图功能模块,它是 Activiti 实现的

虽然说可以通过eclipse、idea等插件去设计画流程图

但是有时候是需要客户动态创建并设计流程图,所以这里就需要把在线设计器集成进自己项目中

所以说,我们要做的就是把 Activiti Modoler 相关模块集成到自己项目中

注意,Activiti 并没有提供接口,这里我们只能通过源码去一步一步集成进来,废话不多说,下面开始

引入文件

首先,maven需要引入新的包(多了很多)

		<dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter-actuator</artifactId>
            <version>6.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-modeler</artifactId>
            <version>5.23.0</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>6.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-diagram-rest</artifactId>
            <version>5.23.0</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-rest</artifactId>
            <version>5.23.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-codec</artifactId>
            <version>1.12</version>
            <exclusions>
                <exclusion>
                    <artifactId>commons-io</artifactId>
                    <groupId>commons-io</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-css</artifactId>
            <version>1.12</version>
        </dependency>

        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-svg-dom</artifactId>
            <version>1.12</version>
        </dependency>

        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-svggen</artifactId>
            <version>1.12</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-explorer</artifactId>
            <version>5.23.0</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-simple-workflow</artifactId>
            <version>5.23.0</version>
        </dependency>

然后,我们需要下载 Activiti 开源包

github:地址https://github.com/Activiti/Activiti/tree/5.x.

下载完解压后,第一步先引入前端文件,位置分别在

\modules\activiti-webapp-explorer2\src\main\webapp
\modules\activiti-webapp-explorer2\src\main\resources

在这里插入图片描述在这里插入图片描述
圈中的都复制到项目中:
在这里插入图片描述


第二步开始引入后端文件,位置分别在

\modules\activiti-modeler\src\main\java\org\activiti\rest\editor\model
\modules\activiti-modeler\src\main\java\org\activiti\rest\editor\main

在这里插入图片描述

也都复制到项目中:
在这里插入图片描述

代码编写

首先修改前端的代码,找到 \editor-app\app-cfg.js 文件,把 contextRoot 对应属性路径删了变成空字符

var ACTIVITI = ACTIVITI || {};

ACTIVITI.CONFIG = {
	'contextRoot' : '',
};

编写控制层类跳转方法,由于在线流程设计器需要 Model 才能初始化,所以在跳转到该页面去需要创建 Model,代码如下:

ModelerController.java

package com.ssactiviti.activiti.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

@Controller
@RequestMapping("/modeler")
public class ModelerController {

    @Resource
    private RepositoryService repositoryService;

    @Resource
    private ObjectMapper objectMapper;

    /**
     * 添加模型
     */
    @GetMapping("/save")
    public void save(HttpServletResponse response) throws IOException {

        //创建模型
        Model modelData = repositoryService.newModel();

        ObjectNode modelObjectNode = objectMapper.createObjectNode();
        //模型名称
        modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, "请假");
        //模型版本
        modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
        //模型详情
        modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, "请假详情");
        //以字符串信息存储进信息属性中
        modelData.setMetaInfo(modelObjectNode.toString());
        //模型名称
        modelData.setName("请假");
        //模型key
        modelData.setKey("leave");

        //完善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.set("stencilset", stencilSetNode);

        //添加模型
        repositoryService.saveModel(modelData);
        repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes(StandardCharsets.UTF_8));

        response.sendRedirect("/static/activiti/modeler.html?modelId=" + modelData.getId());
    }

}

这里因为 Springmvc 会拦截静态资源,所以需要配置静态资源不拦截

MvcConfig.java

package com.ssactiviti.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
class MvcConfig implements WebMvcConfigurer {

	@Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        //定义一个convert转换消息的对象
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        //添加fastjson的配置信息
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setCharset(StandardCharsets.UTF_8);
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);

        //处理中文乱码问题
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.APPLICATION_JSON);

        //在convert中添加配置信息.
        fastConverter.setSupportedMediaTypes(fastMediaTypes);
        fastConverter.setFastJsonConfig(fastJsonConfig);
        //将convert添加到converters中
        converters.add(fastConverter);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/");
    }

	/**
     * 接收PUT、DELETE等请求参数
     * @return
     */
    @Bean
    public FormContentFilter formContentFilter() {
        return new FormContentFilter();
    }
    
}

开始运行程序,访问 http://127.0.0.1:8080/modeler/save,弹出该页面证明整合成功:

在这里插入图片描述

踩坑记

坑点1: js前台报这个错

TypeError: Cannot read property ‘namespace’ of undefined

在这里插入图片描述
小编第一次也踩过这个坑,网上相关描述也非常少

这里Spring Boot2默认采用jackson,当项目使用fastjson的时候,就会出现json转换异常的问题

也就是 ModelEditorJsonRestResource.java 里面的 getEditorJson() 方法返回了字符串,而不是 json 格式的数据导致的

解决办法就是把返回结果转换成 json 返回,方法返回改成Object,这里小编用的是 fastjson,所以对应方法是:

return JSONObject.parseObject(modelNode.toString());

坑点2: js前台报这个错

TypeError: Cannot read property ‘split’ of undefined

在这里插入图片描述
小编也踩过这个坑…导致这个坑的原因有两个

第一检查是否引入了 stencilset.json 文件,并且文件路径是否正确,默认存放resources下级目录
在这里插入图片描述

第二和坑点一同理,只需要在 StencilsetRestResource.java 里面的 getStencilset() 方法返回转成 json 即可

return JSONObject.parseObject(IOUtils.toString(stencilsetStream, "utf-8"));

坑点3: 保存模型的时候报错:

org.springframework.web.HttpMediaTypeNotSupportedException: Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported

这里只需要在ModelSaveRestResource.java里面,把方法参数改成如下即可:

@RequestMapping(value="/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("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) {
      LOGGER.error("Error saving model", e);
      throw new ActivitiException("Error saving model", e);
    }
  }

这几个问题出现的比较多,一般解决了就基本没有问题了


汉化

汉化的过程非常简单,只需要分别用中文版的 stencilset.json 和 en.json 替换下即可:
在这里插入图片描述
汉化之后的效果:
在这里插入图片描述
那么基本代码和效果也演示完毕了

demo也已经放到码云上,获取方式在文章的Spring Boot2 + Activiti6 系列搭建教程开头篇(1) 结尾处

谢谢大家~

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值