springboot集成activiti

写在前面

本次使用springboot2.3.3中集成 activiti-6.0.0,集成完成后发现activiti在线设计器怎么办呢,网上查了资料发现有很多种方式,我了解的有三种,分别是1.去官网下载一个 Activiti UI WAR包然后放到服务器中跑 2.idea下一个bpmn插件(这个插件idea应用都找不到了,只能去idea官网下载下来后进行安装,很久不更新了还有兼容问题,太坑了放弃)3.使用activiti5自带的activiti-editor(就是一套前端代码,把他引入项目中后按照这个前端代码的要求写几个api就可以让他跑起来,为什么是activiti5? 因为他么的他activiti6以后就推荐使用第一种方式了,可是我用第一种的话,不能修改页面,满足不了pm的要求,所以放弃了),这里我选择是第三种!

注意!!该源码中在manager中集成了许多三方如果你本地没有安装该三方的话项目会跑不起来(如hbase),解决方法删除对应的pom依赖、对应的manager、以及对应的application配置项目即可,其他的看README!看README!看README!

引入依赖

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

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

        <!-- 添加解决Activiti6.0.0及以上版本与activiti-modeler的maven引用冲突 -->
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-transcoder</artifactId>
            <version>1.7</version>
        </dependency>

配置application

spring:
  #配置文件相关配置
  profiles:
    active: mysql
  #资源相关配置
  resources:
    static-locations: classpath:/resources/,classpath:/static/
  #servlet相关配置
  servlet:
    multipart:
      enabled: true
      max-file-size: 500MB
      max-request-size: 500MB
  activiti:
    #自动检查、部署流程定义文件
    check-process-definitions: false
    # 检测身份信息表是否存在
    db-identity-used: false
    #自动更新数据库结构
    database-schema-update: true
#    #流程定义文件存放目录
#    process-definition-location-prefix: classpath:/processes/

排除security安全验证

@SpringBootApplication(exclude = {org.activiti.spring.boot.SecurityAutoConfiguration.class,
        SecurityAutoConfiguration.class})
public class JavaModelApplication {
    public static void main(String[] args) {
        SpringApplication.run(JavaModelApplication.class, args);
    }
}

activiti在线设计器资源拷贝

资源下载地址,建议直接到上面给出的源码中直接去复制

拷贝diagram-viewer、editor-app、modeler.html

springboot整合activiti7启动后无法自动生成数据库表 springboot 集成activiti_spring

拷贝stencilset.json

这里copy的是一个英文json,如果你想汉化百度上一大推

springboot整合activiti7启动后无法自动生成数据库表 springboot 集成activiti_spring boot_02

按照activiti-editor要求编写api

editor-app下的app-cfg.js配置

/*
 * Activiti Modeler component part of the Activiti project
 * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
'use strict';

var ACTIVITI = ACTIVITI || {};

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

contextRoot配置为/modeler,那么activiti-editor在访问api时都会在url前面默认前缀为/modeler,看activiti-editor源码可知。如下

springboot整合activiti7启动后无法自动生成数据库表 springboot 集成activiti_spring boot_03

自定义StencilsetRestController

controller访问前缀与app-cfg.js配置的contextRoot保持一致,这个类就一个action,作用就是获取stencilset.json

import io.swagger.annotations.Api;
import org.activiti.engine.ActivitiException;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.*;
import java.io.InputStream;

@RestController
@RequestMapping(value = "/modeler/editor")
@Api(tags = "StencilsetRest相关(前端无需接入)")
public class StencilsetRestController {
    /**
     * 获取stencilset.json
     *
     * @return String
     */
    @GetMapping(value = "/stencilset", produces = "application/json;charset=utf-8")
    public @ResponseBody String getStencilset() {
        //stencilset.json为Model中的工具栏的名称字符,这里在resources下面查找
        InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("stencilset.json");
        try {
            return IOUtils.toString(stencilsetStream, "utf-8");
        } catch (Exception e) {
            throw new ActivitiException("Error while loading stencil set", e);
        }
    }
}

自定义ModelerController

controller访问前缀与app-cfg.js配置的contextRoot保持一致

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.lylbp.manager.activity.service.ModelService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * 这个控制器的接口无需登录权限
 *
 * @author weiwenbin
 */
@Controller
@RequestMapping(value = "/modeler/model")
@Api(tags = "模型相关(前端无需接入)")
public class ModelerController {
    @Resource
    private ModelService modelService;
    ////////////////////页面接口[必须按照官方页面接口形式编写]//////////////////////

    @PostMapping(value = "/{modelId}/save")
    @ApiOperation("保存流程模型")
    @ResponseStatus(value = HttpStatus.OK)
    @ResponseBody
    public Boolean saveModel(@PathVariable String modelId, @RequestParam("name") String modeName,
                             @RequestParam("description") String description,
                             @RequestParam("json_xml") String jsonXml,
                             @RequestParam("svg_xml") String svgXml) {
        return modelService.saveModel(modelId, modeName, description, jsonXml, svgXml);
    }


    @GetMapping(value = "/{modelId}/json", produces = "application/json")
    @ApiOperation("获取模型json")
    @ResponseBody
    public ObjectNode getEditorJson(@PathVariable String modelId) {
        return modelService.getEditorJson(modelId);
    }

自定义controller

import com.lylbp.common.utils.ResResultUtil;
import com.lylbp.common.entity.DataPage;
import com.lylbp.common.entity.PageResResult;
import com.lylbp.common.entity.ResResult;
import com.lylbp.manager.activity.demo.qo.ModelQueryQO;
import com.lylbp.manager.activity.service.ModelService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.activiti.engine.repository.Model;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * 自定义模型
 * 这个控制器的接口要登录权限
 *
 * @author weiwenbin
 * @date 2020/12/14 下午4:03
 */
@Controller
@RequestMapping(value = "/myModeler")
@Api(tags = "自定义模型相关")
public class MyModelerController {
    @Resource
    private ModelService modelService;

    @Resource
    private HttpServletResponse response;

    @GetMapping("/create")
    @ApiOperation("创建流程模型")
    @ResponseBody
    public ResResult<String> createModel() {
        //设置一些默认信息
        String modelName = "new-process";
        String description = "";
        String modelKey = "process";

        return ResResultUtil.success(modelService.createModel(modelName, modelKey, description));
    }

    @GetMapping("/createAndRedirect")
    @ApiOperation("创建流程模型并跳转页面")
    @ResponseBody
    public void createAndRedirect() throws IOException {
        //设置一些默认信息
        String modelName = "new-process";
        String description = "";
        String modelKey = "process";

        String modelId = modelService.createModel(modelName, modelKey, description);
        response.sendRedirect("/modeler/modeler.html?modelId=" + modelId);
    }

    @GetMapping(value = "/deploy/{modelId}")
    @ApiOperation("部署流程模型")
    @ResponseBody
    public ResResult<Boolean> deployModel(@PathVariable String modelId) {
        modelService.deployModel(modelId);
        return ResResultUtil.success(true);
    }

    @DeleteMapping("/remove/{modelId}")
    @ApiOperation("删除模型")
    @ResponseBody
    public ResResult<Boolean> removeByModelIds(@PathVariable("modelId") String modelId) {
        return ResResultUtil.success(modelService.removeByModelId(modelId));
    }

    @PostMapping(value = "/list")
    @ApiOperation("获取分页列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "current", value = "当前页 默认1", defaultValue = "1", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "size", value = "每页显示数 默认10", defaultValue = "10", dataType = "Integer", paramType = "query")
    })
    @ResponseBody
    public ResResult<PageResResult<Model>> list(@RequestBody ModelQueryQO qo,
                                                @RequestParam(defaultValue = "1") Integer current,
                                                @RequestParam(defaultValue = "10") Integer size) {
        DataPage<Model> page = new DataPage<>(current, size);
        List<Model> list = modelService.list(qo, page);
        page.setRecords(list);

        return ResResultUtil.makePageRsp(page);
    }

    @PostMapping(value = "/listNoPage")
    @ApiOperation("获取所有列表")
    @ResponseBody
    public ResResult<List<Model>> listNoPage(@RequestBody ModelQueryQO query) {
        return ResResultUtil.success(modelService.list(query, null));
    }

    @PostMapping(value = "/getModelInfo/{modelId}")
    @ApiOperation("获取模型详情")
    @ResponseBody
    public ResResult<Model> getModelInfo(@PathVariable("modelId") String modelId) {
        return ResResultUtil.success(modelService.getModelInfo(modelId));
    }
}

效果

首先你回发现你的数据库多了很多张表,如下:

springboot整合activiti7启动后无法自动生成数据库表 springboot 集成activiti_spring boot_04

访问

访问创建流程模型并跳转页面:ip:端口myModeler/createAndRedirect

springboot整合activiti7启动后无法自动生成数据库表 springboot 集成activiti_java_05

这样就集成结束了,不过activiti还有很多东西,如保存完要发布啊,以及每张表的数据存储关系啊,以及activiti代码怎么写啊,很多很多,兄弟信我,集成进去只是你的第一步。