SpringBoot2.0集成 Activiti流程设计器

定义

<groupId>com.zhun</groupId>
<artifactId>activiti-editor</artifactId>
<version>0.0.1-SNAPSHOT</version>

继承

<parent>
<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.0.3.RELEASE</version>
	<relativePath/>
</parent>

依赖

<properties>
		<java.version>1.8</java.version>

        <activiti.version>5.22.0</activiti.version>

        <!-- 数据库 Start -->
        <spring-boot-alibaba-druid.version>1.1.16</spring-boot-alibaba-druid.version>
        <mysql-connector.version>8.0.15</mysql-connector.version>
        <!-- 数据库 End -->
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

        <!-- web相关 Start-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
        </dependency>
        <!-- web相关 End-->

        <!-- 数据库 Start -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${spring-boot-alibaba-druid.version}</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql-connector.version}</version>
        </dependency>
        <!-- 数据库 End -->

        <!-- Activiti Start -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter-basic</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter-actuator</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-explorer</artifactId>
            <version>${activiti.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.vaadin</groupId>
                    <artifactId>vaadin</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.vaadin.addons</groupId>
                    <artifactId>dcharts-widget</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>activiti-simple-workflow</groupId>
                    <artifactId>org.activiti</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Activiti End -->

        <!-- 工具 Start -->
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-codec</artifactId>
            <version>1.7</version>
        </dependency>
        <!-- 工具 End -->

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

配置文件application.yml

server:
  port: 8080
  servlet:
      context-path:

spring:
  datasource:
    druid:
      url: jdbc:mysql://127.0.0.1:3306/activiti5?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      initial-size: 1
      min-idle: 1
      max-active: 20
      test-on-borrow: true
      driver-class-name: com.mysql.cj.jdbc.Driver
  # activiti相关配置
  activiti:
    check-process-definitions: false #自动检查、部署流程定义文件
    database-schema-update: true #自动更新数据库结构
    process-definition-location-prefix: classpath:/processes/bpmn/ #流程定义文件存放目录
    #process-definition-location-suffixes: #流程文件格式
    #  - **.bpmn20.xml
    #  - **.bpmn
    #保存历史数据级别设置为full最高级别,便于历史数据的追溯
    history-level: full
    async-executor-activate: false
    #禁用activiti自带用户与用户组相关表(共计4张表,禁用后剩24张表)
    db-identity-used: true
    #禁用activiti历史表(共计8张表,禁用后剩下20张表)
    #db-history-used: false
    rest-api-enabled: true

  thymeleaf:
    cache: false
    mode: HTML5
    encoding: UTF-8
    servlet:
      content-type: text/html

mybatis-plus:
  configuration:
    call-setters-on-nulls: true
    map-underscore-to-camel-case: true
  • 自行创建数据库activiti5
  • 自行创建数据库表

接口源码
StencilsetRestResource

@RestController
@RequestMapping(value = "service")
public class StencilsetRestResource {
  
  @RequestMapping(value="/editor/stencilset", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
  public @ResponseBody String getStencilset() {
    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);
    }
  }
}

ModelEditorJsonRestResource

@RestController
@RequestMapping(value = "/service")
public class ModelEditorJsonRestResource implements ModelDataJsonConstants {
  
  protected static final Logger LOGGER = LoggerFactory.getLogger(ModelEditorJsonRestResource.class);
  
  @Autowired
  private RepositoryService repositoryService;
  
  @Autowired
  private ObjectMapper objectMapper;
  
  @RequestMapping(value="/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()), "utf-8"));
        modelNode.put("model", editorJsonNode);
        
      } catch (Exception e) {
        LOGGER.error("Error creating model JSON", e);
        throw new ActivitiException("Error creating model JSON", e);
      }
    }
    return modelNode;
  }
}

ModelSaveRestResource

@RestController
@RequestMapping(value = "/service")
public class ModelSaveRestResource implements ModelDataJsonConstants {
  
  protected static final Logger LOGGER = LoggerFactory.getLogger(ModelSaveRestResource.class);

  @Autowired
  private RepositoryService repositoryService;
  
  @Autowired
  private ObjectMapper objectMapper;
  
  @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);
    }
  }
}

扩展接口

@Controller
public class IndexController {
    private static final Logger logger = LoggerFactory.getLogger(IndexController.class);

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ObjectMapper objectMapper;

    @GetMapping({"", "index"})
    public String index(ModelMap modelMap) {
        modelMap.put("modelList", repositoryService.createModelQuery().list());
        return "index";
    }

    @GetMapping("modeler")
    public String modeler() {
        return "modeler";
    }

    /**
     * 创建模型
     *
     * @param response
     * @param name     模型名称
     * @param key      模型key
     */
    @RequestMapping(value = "/create",method = RequestMethod.GET)
    public void create(HttpServletResponse response, String name, String key) throws IOException {
        logger.info("创建模型入参name:{},key:{}", name, key);
        Model model = repositoryService.newModel();
        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
        modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, "");
        modelNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
        model.setName(name);
        model.setKey(key);
        model.setMetaInfo(modelNode.toString());
        repositoryService.saveModel(model);
        createObjectNode(model.getId());
        response.sendRedirect("/modeler?modelId=" + model.getId());
        logger.info("创建模型结束,返回模型ID:{}", model.getId());
    }

    /**
     * 创建模型时完善ModelEditorSource
     *
     * @param modelId
     */
    @SuppressWarnings("deprecation")
    private void createObjectNode(String modelId) {
        logger.info("创建模型完善ModelEditorSource入参模型ID:{}", modelId);
        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);
        try {
            repositoryService.addModelEditorSource(modelId, editorNode.toString().getBytes("utf-8"));
        } catch (Exception e) {
            logger.info("创建模型时完善ModelEditorSource服务异常:{}", e);
        }
        logger.info("创建模型完善ModelEditorSource结束");
    }
}

设计器源码复制

  • resources/static/diagram-viewer
  • resources/static/editor-app
  • resources/stencilset.json
  • resources/templates/modeler.html
  • resources/tempaltes/index.html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Activiti 5.22 设计器</title>
</head>
<body>
<h2>
    <a href='/create?name=activiti&key=123456'>绘制流程</a>
</h2>
<div>
    <table width="100%">
        <tr>
            <td width="10%">模型编号</td>
            <td width="10%">版本</td>
            <td width="20%">模型名称</td>
            <td width="20%">模型key</td>
            <td width="40%">操作</td>
        </tr>
        <tr th:each="model:${modelList}">
            <td width="10%" th:text="${model.id}"></td>
            <td width="10%" th:text="${model.version}"></td>
            <td width="20%" th:text="${model.name}"></td>
            <td width="20%" th:text="${model.key}"></td>
            <td width="40%">
                <a th:href="|/modeler?modelId=${model.id}|">编辑</a>
                <a th:href="|/publish?modelId=${model.id}|">发布</a>
                <a th:href="|/revokePublish?modelId=${model.id}|">撤销</a>
                <a th:href="|/delete?modelId=${model.id}|">删除</a>
            </td>
        </tr>
    </table>
</div>
</body>
</html>

访问

http://localhost:8080

码云地址

https://gitee.com/piaoyi95/acticiti-editor
发布了8 篇原创文章 · 获赞 2 · 访问量 177

猜你喜欢

转载自blog.csdn.net/zhemenanna/article/details/104263298