Spring boot整合activiti modeler 5.22

标签: spring-boot activiti整合页面流程设计器 activiti activiti-工作流 activiti工作流
13694人阅读 评论(21) 收藏 举报
分类:

Spring boot 整合activiti modeler

前言

瞎整了一个晚上加一个上午,终于整合完成了,记录以便下次使用

Spring boot版本:1.5.3

activiti版本:5.22.0

一、目录结构

目录结构

其中:

二、整合流程

2.1 复制文件

首先从官方下载activiti5.22.0版本的全代码包,并在本地解压待用

  • activiti-webapp-explorer2中复制src\main\java\org\activiti\explorer\servlet路径下的文件(图中的A部分)到本地项目中(如启动后无法访问静态资源文件,则删除DispatherServletConfiguration.java这个文件
  • activiti-webapp-explorer2中复制src\main\resources路径下的stencilset.json文件到本地项目的resources目录下(我这里为了管理放在了resources/activiti/modeler目录下)
  • activiti-webapp-explorer2中复制src\main\webapp路径下的文件(图中C部分)到本地项目的resources/public/static目录下
  • activiti-modeler中复制src\main\java\org\activiti\rest\editor路径下的文件(图中的B部分)到本地项目中

以上拷贝的路径参考上图

2.2 修改文件

为了整合能够达到效果,我们需要对以下文件进行修改

1)修改本地项目的pom.xml,增加如下依赖

<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-rest</artifactId>
    <version>${activiti.version}</version>
</dependency>

<dependency>
    <groupId>org.apache.xmlgraphics</groupId>
    <artifactId>batik-codec</artifactId>
    <version>1.7</version>
</dependency>
<dependency>
    <groupId>org.apache.xmlgraphics</groupId>
    <artifactId>batik-css</artifactId>
    <version>1.7</version>
</dependency>
<dependency>
    <groupId>org.apache.xmlgraphics</groupId>
    <artifactId>batik-svg-dom</artifactId>
    <version>1.7</version>
</dependency>
<dependency>
    <groupId>org.apache.xmlgraphics</groupId>
    <artifactId>batik-svggen</artifactId>
    <version>1.7</version>
</dependency>
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-explorer</artifactId>
    <version>${activiti.version}</version>
</dependency>
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-diagram-rest</artifactId>
    <version>${activiti.version}</version>
</dependency>
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-simple-workflow</artifactId>
    <version>${activiti.version}</version>
</dependency>
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring</artifactId>
    <version>${activiti.version}</version>
</dependency>

2)修改DispatcherServletConfiguration.java
改为如下:

@Configuration
@ComponentScan({"org.activiti.rest.editor", "org.activiti.rest.diagram"})
public class DispatcherServletConfiguration {
  private final Logger log = LoggerFactory.getLogger(DispatcherServletConfiguration.class);

  @Bean
  public SessionLocaleResolver localeResolver() {
    return new SessionLocaleResolver();
  }

  @Bean
  public LocaleChangeInterceptor localeChangeInterceptor() {
    log.debug("Configuring localeChangeInterceptor");
    LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
    localeChangeInterceptor.setParamName("language");
    return localeChangeInterceptor;
  }

  @Bean
  public RequestMappingHandlerMapping requestMappingHandlerMapping() {
    log.debug("Creating requestMappingHandlerMapping");
    RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping();
    requestMappingHandlerMapping.setUseSuffixPatternMatch(false);
    Object[] interceptors = {localeChangeInterceptor()};
    requestMappingHandlerMapping.setInterceptors(interceptors);
    return requestMappingHandlerMapping;
  }

}

3)修改StencilsetRestResource.java(如果在拷贝stencilset.json时没有放在resources目录下)

InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("stencilset.json");

改为

InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("activiti.modeler/stencilset.json");

4)修改StencilsetRestResource.javaModelEditorJsonRestResource.javaModelSaveRestResource.java

统一在类上加

@RequestMapping(value = "/service")

5)修改Spring boot 启动类Application.java

在里面增加注解

@ComponentScan({"org.activiti.rest.diagram", "com.westcatr.rd"})
@EnableAsync

同时增加一个filter

@Bean
public JsonpCallbackFilter filter(){
    return new JsonpCallbackFilter();
}

6)修改editor-app下的app-cfg.js,将

ACTIVITI.CONFIG = {
    'contextRoot' : 'activiti-webapp-explorer2/service',
};

改为

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

7)修改ModelSaveRestResource.java(主要是因为集成后保存时候报400错误)
将代码改为如下

@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, @RequestParam("name") String name,
                        @RequestParam("json_xml") String json_xml, @RequestParam("svg_xml") String svg_xml,
                        @RequestParam("description") String description) {//对接收参数进行了修改
    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);
    }
  }
}

8)修改activiti-modeler编辑关闭时返回的路径

整合完成后,启动项目,访问http://localhost:8080/static/modeler.html?modelId=1我们可以看到一个空白的编辑器,里面什么也木有。原因是什么呢,是因为我们的modelId=1是乱输入的,他应该要和数据库表ACT_RE_MODEL对应起来才对。那么这张表里的数据如何来的呢,我们需要自己写一个Controller,对应封装4个方法:1.新建一个空的模型;2.所有模型列表;3.发布模型;4.删除模型;(activiti已提供了保存修改和获取模型节点信息的方法,就是上面C部分的那3个类)

参考代码(该部分代码感谢:http://www.jianshu.com/p/cf766a713a86


@RestController
@RequestMapping("models")
public class ModelerController {

    @Autowired
    ProcessEngine processEngine;
    @Autowired
    ObjectMapper objectMapper;

    /**
     * 新建一个空模型
     * @return
     * @throws UnsupportedEncodingException
     */
    @PostMapping
    public Object newModel() throws UnsupportedEncodingException {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //初始化一个空模型
        Model model = repositoryService.newModel();

        //设置一些默认信息
        String name = "new-process";
        String description = "";
        int revision = 1;
        String key = "process";

        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
        modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
        modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);

        model.setName(name);
        model.setKey(key);
        model.setMetaInfo(modelNode.toString());

        repositoryService.saveModel(model);
        String id = model.getId();

        //完善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.put("stencilset", stencilSetNode);
        repositoryService.addModelEditorSource(id,editorNode.toString().getBytes("utf-8"));
        return ToWeb.buildResult().redirectUrl("/modeler.html?modelId="+id);
    }

    /**
     * 获取所有模型
     * @return
     */
    @GetMapping
    public Object modelList(){
        RepositoryService repositoryService = processEngine.getRepositoryService();
        List<Model> models = repositoryService.createModelQuery().list();
        return ToWeb.buildResult().putData("models", models);
    }

    /**
     * 删除模型
     * @param id
     * @return
     */
    @DeleteMapping("{id}")
    public Object deleteModel(@PathVariable("id")String id){
        RepositoryService repositoryService = processEngine.getRepositoryService();
        repositoryService.deleteModel(id);
        return ToWeb.buildResult().refresh();
    }

    /**
     * 发布模型为流程定义
     * @param id
     * @return
     * @throws Exception
     */
    @PostMapping("{id}/deployment")
    public Object deploy(@PathVariable("id")String id) throws Exception {

        //获取模型
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Model modelData = repositoryService.getModel(id);
        byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());

        if (bytes == null) {
            return ToWeb.buildResult().status(Config.FAIL)
                    .msg("模型数据为空,请先设计流程并成功保存,再进行发布。");
        }

        JsonNode modelNode = new ObjectMapper().readTree(bytes);

        BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
        if(model.getProcesses().size()==0){
            return ToWeb.buildResult().status(Config.FAIL)
                    .msg("数据模型不符要求,请至少设计一条主线流程。");
        }
        byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);

        //发布流程
        String processName = modelData.getName() + ".bpmn20.xml";
        Deployment deployment = repositoryService.createDeployment()
                .name(modelData.getName())
                .addString(processName, new String(bpmnBytes, "UTF-8"))
                .deploy();
        modelData.setDeploymentId(deployment.getId());
        repositoryService.saveModel(modelData);

        return ToWeb.buildResult().refresh();
    }
}

三、activiti modeler 导入现有流程文件

我们经常会使用其他的工具来制作bpmn文件,如使用eclipse的activiti designer,在我们的项目集成好activiti modeler后,就不需要再用其他工具来编辑了。那么如何将现有的bpmn文件导入到继承好的activiti modeler里呢。

通过对源码的查看,可以从activiti-exporer中的ImportUploadReceiver.java里找到一些思路,我们可以新建一个上传方法,即可上传我们的现有bpmn文件。代码如下:

@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
    public void deployUploadedFile(
            @RequestParam("uploadfile") MultipartFile uploadfile) {
        InputStreamReader in = null;
        try {
            try {
                boolean validFile = false;
                String fileName = uploadfile.getOriginalFilename();
                if (fileName.endsWith(".bpmn20.xml") || fileName.endsWith(".bpmn")) {
                    validFile = true;

                    XMLInputFactory xif = XmlUtil.createSafeXmlInputFactory();
                    in = new InputStreamReader(new ByteArrayInputStream(uploadfile.getBytes()), "UTF-8");
                    XMLStreamReader xtr = xif.createXMLStreamReader(in);
                    BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);

                    if (bpmnModel.getMainProcess() == null || bpmnModel.getMainProcess().getId() == null) {
//                        notificationManager.showErrorNotification(Messages.MODEL_IMPORT_FAILED,
//                                i18nManager.getMessage(Messages.MODEL_IMPORT_INVALID_BPMN_EXPLANATION));
                        System.out.println("err1");
                    } else {

                        if (bpmnModel.getLocationMap().isEmpty()) {
//                            notificationManager.showErrorNotification(Messages.MODEL_IMPORT_INVALID_BPMNDI,
//                                    i18nManager.getMessage(Messages.MODEL_IMPORT_INVALID_BPMNDI_EXPLANATION));
                            System.out.println("err2");
                        } else {

                            String processName = null;
                            if (StringUtils.isNotEmpty(bpmnModel.getMainProcess().getName())) {
                                processName = bpmnModel.getMainProcess().getName();
                            } else {
                                processName = bpmnModel.getMainProcess().getId();
                            }
                            Model modelData;
                            modelData = repositoryService.newModel();
                            ObjectNode modelObjectNode = new ObjectMapper().createObjectNode();
                            modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processName);
                            modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
                            modelData.setMetaInfo(modelObjectNode.toString());
                            modelData.setName(processName);

                            repositoryService.saveModel(modelData);

                            BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
                            ObjectNode editorNode = jsonConverter.convertToJson(bpmnModel);

                            repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));
                        }
                    }
                } else {
//                    notificationManager.showErrorNotification(Messages.MODEL_IMPORT_INVALID_FILE,
//                            i18nManager.getMessage(Messages.MODEL_IMPORT_INVALID_FILE_EXPLANATION));
                    System.out.println("err3");
                }
            } catch (Exception e) {
                String errorMsg = e.getMessage().replace(System.getProperty("line.separator"), "<br/>");
//                notificationManager.showErrorNotification(Messages.MODEL_IMPORT_FAILED, errorMsg);
                System.out.println("err4");
            }
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
//                    notificationManager.showErrorNotification("Server-side error", e.getMessage());
                    System.out.println("err5");
                }
            }
        }
    }

补充:上面的是之前做项目整合时的流程记录,看到有朋友说不能够整合,今天按照流程重新整合了一遍,并上传了代码,传送门:http://download.csdn.net/detail/chenhai201/9862887

查看评论

在VC中实现程序在启动时隐藏

    最近经常见论坛上有人问,程序在启动时如何隐藏。以下是我总结的一些方法,欢迎大家讨论,找出更好的方法。    对于这类问题,大家最容易想到的可能就是在PreCreateWindow中添加cs.s...
  • AttaBoy
  • AttaBoy
  • 2002-03-03 09:18:00
  • 1225

一、SpringBoot集成Activiti Modeler(坑已踩)

一、集成准备 下载activiti源码及activiti-5.22.zip源码下载GitHub地址,下载之后使用命令git checkout 5.22.0-release切换到5.22.0-rel...
  • KingBoyWorld
  • KingBoyWorld
  • 2017-08-23 10:55:56
  • 1605

activiti入门六(集成新版Activiti Modeler与Rest服务)

目前activiti提供的Activiti Modeler有两套,从Activiti5.17后,发布了新的Activiti Modeler组件。本文主要介绍如何在项目中集成最新的Activiti Mo...
  • whatlookingfor
  • whatlookingfor
  • 2016-10-28 18:26:06
  • 11347

spring boot 整合 activiti 踩过的坑 (持续更新)

1.首先是maven添加依赖各种报错。 org.activiti activiti-spring-boot-starter-basic 5.22.0 ...
  • y670340559
  • y670340559
  • 2017-09-06 16:13:39
  • 5974

spring boot整合activiti modeler实例源码下载

  • 2017年06月06日 23:56
  • 1.48MB
  • 下载

springboot整合activiti modeler出现验证问题

网上一大堆关于解决SpringBoot整合ActivitiModeler模块后需要需要密码的问题解决方法,都是你抄我的,我抄你的 解决方法: http://www.yayihouse.com/ya...
  • qq_30908729
  • qq_30908729
  • 2018-03-12 14:06:57
  • 61

三、解决Springboot集成ActivitiModel提示输入密码的问题

一、原因分析先要知道两点 - SpringBoot会根据引入的Jar包而自动配置相应的功能。 - ActivitiModeler中引用了Spring Security的Jar。(是一个安全或者说权...
  • KingBoyWorld
  • KingBoyWorld
  • 2017-08-30 09:32:52
  • 1901

Spring boot 整合activiti以及大量实例

1,Spring boot 整合activiti modeler: 感谢其他作者,参考:http://blog.csdn.net/chenhai201/article/details/72668275...
  • lgllionky
  • lgllionky
  • 2017-11-16 15:14:37
  • 1634

springboot整合activiti-modeler

  • 2018年01月31日 15:27
  • 3.02MB
  • 下载

整合Activiti-modeler并汉化

整合Activiti-modeler并汉化
  • murongxuesheng
  • murongxuesheng
  • 2016-12-16 17:24:30
  • 3876
    个人资料
    等级:
    访问量: 3万+
    积分: 434
    排名: 11万+
    最新评论