欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【弄nèng - Activiti6】Springboot搭建Activiti整合流程设计器

程序员文章站 2022-06-20 11:58:25
...

开发工具使用IDE,基于Springboot项目搭建
Activiti整合流程设计器是5.22版本包内的工具,6.0以上没有。不过使用无异,直接用它就行了。它可以是我们快速构建Activiti流程图,方便使用,便于管理。
本文不止整合Activiti流程设计器,也包含Springboot整合Activiti

1. 引入依赖

pom.xml
这里只列出核心pom,像数据库,springboot等其他依赖自己添加

		<!-- activiti -->
		<properties>
			<activiti.version>6.0.0</activiti.version>
		</properties>
	
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter-basic</artifactId>
            <version>${activiti.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.mybatis</groupId>
                    <artifactId>mybatis</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>

2. Activiti配置

# activiti配置
  activiti:
    # true  代表没有表就自动创建
    database-schema-update: true
    # 记录级别,默认audit
    history-level: full
    # (可选)自动部署验证设置:true-开启(默认)、false-关闭
    check-process-definitions: false
    # (可选)默认流程定义文件存放目录
    process-definition-location-prefix: classpath:/processes/

3. 整合流程设计器

3.1下载流程设计器

activiti-5.22.0下载地址

链接:https://pan.baidu.com/s/1FEznQtYvTx-qiAB7_MUoJQ
提取码:a56t

下载官方activiti-5.22.0的包,解压wars下面的activiti-explorer.war,把diagram-viewer、editor-app、modeler.html复制到Springboot项目的static目录下,这个是activiti的在线设计器,modeler.html是主界面。
【弄nèng - Activiti6】Springboot搭建Activiti整合流程设计器

3.2 汉化

stencilset.json下载地址

链接:https://pan.baidu.com/s/15koYuOoV42PIHQeB4RsHbw
提取码:qnxd

下载stencilset.json,放在Springboot项目的static目录下

3.3 修改配置

在editor-app/app-cfg.js中contextRoot是编辑器的后台服务的url,去掉activiti-explorer
【弄nèng - Activiti6】Springboot搭建Activiti整合流程设计器
改成
【弄nèng - Activiti6】Springboot搭建Activiti整合流程设计器

4.流程设计器后端服务

  1. StencilsetRestResource 获取编辑器组件及配置项信息。
  2. ModelEditorJsonRestResource 根据modelId获取model的节点信息,编辑器根据返回的json进行绘图。
  3. ModelSaveRestResource 编辑器制图之后,将节点信息以json的形式提交给这个Controller,然后由其进行持久化操作。

将以下ActManageController.java类复制你的项目
@RequestMapping("/service") 是跟editor-app/app-cfg.js中contextRoot对应的

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.it.cloud.common.xss.XssHttpServletRequestWrapper;
import org.activiti.engine.ActivitiException;
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.lang.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * @author 司马缸砸缸了
 * @date 2019/8/23 15:40
 * @description activiti editor管理类
 */
@RestController
@RequestMapping("/service")
public class ActManageController {
    @Autowired
    ObjectMapper objectMapper;
    @Autowired
    private RepositoryService repositoryService;

    /**
     * stencilset:获取编辑器组件及配置项信息
     *
     * @return stencilset.json
     */
    @RequestMapping("/editor/stencilset")
    public String getStencilset() {
        InputStream stencilsetStream = this.getClass().getResourceAsStream("/static/stencilset.json");
        try {
            return IOUtils.toString(stencilsetStream, "utf-8");
        } catch (Exception e) {
            throw new ActivitiException("Error while loading stencil set", e);
        }
    }

    /**
     * 模型详情
     *
     * @param modelId
     * @return
     */
    @RequestMapping("/model/{modelId}/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("name", model.getName());
                }
                modelNode.put("modelId", model.getId());
                ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(
                        new String(repositoryService.getModelEditorSource(model.getId()), "utf-8"));
                modelNode.set("model", editorJsonNode);

            } catch (Exception e) {
                throw new ActivitiException("Error creating model JSON", e);
            }
        }
        return modelNode;
    }

    /**
     * 保存
     *
     * @param modelId
     * @param name
     * @param jsonXml
     * @param svgXml
     * @param description
     */
    @RequestMapping("/model/{modelId}/save")
    @RequiresPermissions("act:manage:save")
    public void saveModel(@PathVariable String modelId, @RequestParam("name") String name,
                          @RequestParam("json_xml") String jsonXml, @RequestParam("svg_xml") String svgXml,
                          @RequestParam("description") String description, HttpServletRequest request) {
        HttpServletRequest orgRequest = XssHttpServletRequestWrapper.getOrgRequest(request);
        try {
            // 因为添加了html过滤,直接通过参数得不到html符号(XssFilter)
            svgXml = orgRequest.getParameterMap().get("svg_xml")[0];
            Model model = repositoryService.getModel(modelId);
            ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
            modelJson.put("name", name);
            modelJson.put("description", description);
            model.setMetaInfo(modelJson.toString());
            model.setName(name);
            repositoryService.saveModel(model);
            repositoryService.addModelEditorSource(model.getId(), jsonXml.getBytes(StandardCharsets.UTF_8));

            InputStream svgStream = new ByteArrayInputStream(svgXml.getBytes(StandardCharsets.UTF_8));
            TranscoderInput input = new TranscoderInput(svgStream);
            PNGTranscoder transcoder = new PNGTranscoder();
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            TranscoderOutput output = new TranscoderOutput(outStream);
            transcoder.transcode(input, output);
            final byte[] result = outStream.toByteArray();
            repositoryService.addModelEditorSourceExtra(model.getId(), result);
            outStream.close();
        } catch (Exception e) {
            throw new ActivitiException("Error saving model", e);
        }
    }
}

5. Activiti乱码配置

ActivitiConfig.java

import org.activiti.engine.*;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.io.IOException;

/**
 * 工作流配置
 *
 * @author 司马缸砸缸了
 */
@Component
public class ActivitiConfig implements ProcessEngineConfigurationConfigurer {

    /**
     * 解決工作流生成图片乱码问题
     *
     * @param processEngineConfiguration processEngineConfiguration
     */
    @Override
    public void configure(SpringProcessEngineConfiguration processEngineConfiguration) {
        processEngineConfiguration.setActivityFontName("宋体");
        processEngineConfiguration.setAnnotationFontName("宋体");
        processEngineConfiguration.setLabelFontName("宋体");
    }

}

6.启动类

排除SecurityAutoConfiguration,不然启动会报错

@SpringBootApplication(exclude = SecurityAutoConfiguration.class)

7.测试

需要数据库中已经存在model记录,才可以看到效果,只要替换modelId就可以了。
访问 http:localhost:8080/modeler.html?modelId=25001
【弄nèng - Activiti6】Springboot搭建Activiti整合流程设计器


以上代码我已经整合到IT-CLOUD项目中

代码地址

IT-CLOUD :IT服务管理平台,集成基础服务,中间件服务,监控告警服务等
开源项目,持续更新中,喜欢请 Star~

相关标签: activiti