springboot集成activity6.0.0

个人博客地址:www.wzbjsz.cn

在线浏览地址:activiti.wzbjsz.cn

什么是工作流?

工作流(Workflow),就是通过计算机对业务流程自动化执行管理。它主要解决的是“使在多个参与者之间按照某种预定义的规则自动进行传递文档、信息或任务的过程,从而实现某个预期的业务目标,或者促使此目标的实现”。

什么是Activiti?

Alfresco软件在2010年5月17日宣布Activiti业务流程管理(BPM)开源项目的正式启动,其首席架构师由业务流程管理BPM的专家 Tom Baeyens担任,Tom Baeyens就是原来jbpm的架构师,而jbpm是一个非常有名的工作流引擎,当然activiti也是一个工作流引擎。

Activiti是一个工作流引擎, activiti可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言(BPMN2.0)进行定义,业务系统按照预先定义的流程进行执行,实现了业务系统的业务流程由activiti进行管理,减少业务系统由于流程变更进行系统升级改造的工作量,从而提高系统的健壮性,同时也减少了系统开发维护成本。

什么是BPMN?

BPMN(Business Process Model And Notation)- 业务流程模型和符号 是由BPMI(Business Process Management Initiative)开发的一套标准的业务流程建模符号,使用BPMN提供的符号可以创建业务流程。 2004年5月发布了BPMN1.0规范.BPMI于2005年9月并入OMG(The Object Management Group对象管理组织)组织。OMG于2011年1月发布BPMN2.0的最终版本。

 

具体发展历史如下:


BPMN 是目前被各 BPM 厂商广泛接受的 BPM 标准。Activiti 就是使用 BPMN 2.0 进行流程建模、流程执行管理,它包括很多的建模符号,比如:

Event 用一个圆圈表示,它是流程中运行过程中发生的事情。


活动用圆角矩形表示,一个流程由一个活动或多个活动组成

 

一个bpmn图形的例子:

Bpmn图形其实是通过xml表示业务流程,上边的.bpmn文件使用文本编辑器打开:

一:在项目pom.xml文件中添加activity依赖。

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

二:修改启动类。

@SpringBootApplication(exclude={org.activiti.spring.boot.SecurityAutoConfiguration.class})

三:流程文件。
在src/main/java/resources目录下新建processes目录,并在该目录下新增一个业务流程文件(默认以.bpmn20.xml或.bpmn为后缀名)(activity默认校验resources下的processes文件夹里的流程文件,如果没有processes目录并且目录下没有流程文件会报错class path resource [processes/] cannot be resolved to URL because it does not exist),
可以在配置文件中配置spring.activiti.check-process-definitions=false,设置为不校验,这样就不会报错。
四:修改activity默认的id生成策略。
1.activiti默认的ID生成策略在高并发场景下会出现ID重复的情况,因此在高并发场景下建议采用UUID的策略。
2.传统的spring在配置文件中添加idGenerator属性:

    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
        <!-- UUID作为主键生成策略 -->
        <property name="idGenerator" ref="idGenerator" />
    </bean>

3.springboot中在配置类中修改idGenerator。
需要写一个类实现IdGenerator,并重写getNextId()方法;
activity也内置了一个实现类org.activiti.engine.impl.persistence.StrongUuidGenerator,生成的uuid是带'-'的

package com.mycompany.myapp.config;

import org.activiti.spring.SpringProcessEngineConfiguration;
import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
import org.springframework.context.annotation.Configuration;

import com.mycompany.myapp.utils.idGenerator;

/**
* @author www.wzbjsz.cn
* @date 2019-01-09 10:26:47
*/
@Configuration
public class ActivitiConfig implements ProcessEngineConfigurationConfigurer {

    @Override
    public void configure(SpringProcessEngineConfiguration springProcessEngineConfiguration) {
        springProcessEngineConfiguration.setIdGenerator(new idGenerator());
    }

}
package com.mycompany.myapp.utils;

import java.util.UUID;

import org.activiti.engine.impl.cfg.IdGenerator;

/**
* @author www.wzbjsz.cn
* @date 2019-01-09 10:47:59
*/
public class idGenerator implements IdGenerator{

    /**
     * 封装JDK自带的UUID, 通过Random数字生成, 中间无-分割.
     */
    public static String uuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * Activiti ID 生成
     */
    @Override
    public String getNextId() {
        return IdGen.uuid();
    }

}

五:配置文件属性:
1.spring.activiti.database-schema-update

spring.activiti.database-schema-update=true

databaseSchemaUpdate配置项可以设置流程引擎启动和关闭时数据库执行的策略。 databaseSchemaUpdate有以下四个值:

false:false为默认值,设置为该值后,Activiti在启动时,会对比数据库表中保存的版本,如果版本不匹配时,将在启动时抛出异常。
true:设置为该值后,Activiti会对数据库中所有的表进行更新,如果表不存在,则Activiti会自动创建。
create-drop:Activiti启动时,会执行数据库表的创建操作,在Activiti关闭时,执行数据库表的删除操作。
drop-create:Activiti启动时,执行数据库表的删除操作在Activiti关闭时,会执行数据库表的创建操作。

设置为true后启动应用,会在数据库里创建28张表,表创建好之后停止应用,设置为false,每次应用启动不检查Activiti数据表是否存在及版本号是否匹配,以提升应用启动速度。
2.spring.activiti.history-level

#保存历史数据级别设置为full最高级别,便于历史数据的追溯
spring.activiti.history-level=full

对于历史数据,保存到何种粒度,Activiti提供了history-level属性对其进行配置。history-level属性有点像log4j的日志输出级别,该属性有以下四个值:

none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。
activity:级别高于none,保存流程实例与流程行为,其他数据不保存。
audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。
full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。

3.spring.activiti.check-process-definitions

#关闭activiti自动部署(使用流程设计器部署,不使用具体文件访问方式)
spring.activiti.check-process-definitions=false

六:集成在线流程设计器Activiti Modeler。
1.pom文件添加activiti-modeler依赖。

        <!-- https://mvnrepository.com/artifact/org.activiti/activiti-modeler -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-modeler</artifactId>
            <version>5.22.0</version>
            <exclusions>
                <exclusion>
                        <groupId>org.activiti</groupId>
                        <artifactId>activiti-bpmn-model</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

2.下载activiti5.22.0源码https://github.com/Activiti/Activiti/tree/activiti-5.22.0
3.复制Activiti 5.22.0中Activiti\modules\activiti-webapp-explorer2\src\main\webapp中的diagram-viewer、editor-app两个文件夹和modeler.html文件到Spring Boot项目resources目录下的static文件夹下。

image.png

 

image.png


4.修改resource/static/editor-app/app-cfg.js。

image.png


改为:

 

var ACTIVITI = ACTIVITI || {};

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

5.复制Activiti\modules\activiti-webapp-explorer2\src\main\resources中的stencilset.json文件到Spring Boot项目中的resources目录下,activiti自带是英文的。
6.将Activiti 5.22.0源码中activiti-modeler中的下列3个java文件复制到自己的项目中,并在三个java类上添加注解@RequestMapping("/service")。(/service与上面app-cfg.js中保持一致)

 

image.png

 

image.png

 

7.修改ModelSaveRestResource.java文件:

/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mycompany.myapp.modeler.editor.model;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

import org.activiti.editor.constants.ModelDataJsonConstants;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * @author Tijs Rademakers
 */
@RestController
@RequestMapping("/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);
        }
      }
}

8.测试创建模型。

    /**
     * 新建一个空模型
     * @return
     * @throws UnsupportedEncodingException
     */
    @GetMapping("/create")
    public void newModel(HttpServletRequest request,HttpServletResponse response) throws Exception {
        //初始化一个空模型
        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.set("stencilset", stencilSetNode);
        repositoryService.addModelEditorSource(id,editorNode.toString().getBytes("utf-8"));
        response.sendRedirect("/modeler.html?modelId="+id);
    }

9.请求创建模型接口后,显示如下页面表示成功:

image.png


10.去掉Activiti Afresco的logo标题栏,并且把样式上的空白栏去掉。
1)修改modeler.html中的以下内容,注意不要把该文本删除,建议加style=”display:none”,删除后其会造成底层下的一些内容有40个像数的东西显示不出来,也可以直接删除掉。

 

    <div style="display:none" class="navbar navbar-fixed-top navbar-inverse" role="navigation" id="main-header">
        <div class="navbar-header">
            <a href="" ng-click="backToLanding()" class="navbar-brand"
               title="{{'GENERAL.MAIN-TITLE' | translate}}"><span
                    class="sr-only">{{'GENERAL.MAIN-TITLE' | translate}}</span></a>
        </div>
    </div>

2)在editor-app/css/style-common.css中,把以下样式的padding-top部分改为0px;

.wrapper.full {
    padding: 0px 0px 0px 0px;
    overflow: hidden;
    max-width: 100%;
    min-width: 100%;
}

11.保存模型如果报错获取不到参数。(http://www.wzbjsz.cn),添加过滤器:

package com.mycompany.myapp.config;

import javax.servlet.annotation.WebFilter;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.HttpPutFormContentFilter;

/**
* @author www.wzbjsz.cn
* @date 2019-01-20 15:47:39
*/
@Component
@WebFilter(urlPatterns = "/*", filterName = "putFilter")
@Order(Integer.MIN_VALUE)
public class PutFilter extends HttpPutFormContentFilter {

}

七.modeler相关方法的封装。

package com.lhtc.jv.vo;

import java.io.Serializable;

import javax.validation.constraints.NotNull;

import lombok.Data;

/**
* @author www.wzbjsz.cn
* @date 2019-01-21 14:38:54
*/
@Data
public class ActModelVO implements Serializable{

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    private String id;//模型id

    @NotNull
    private String name;//模型名称

    @NotNull
    private String key;//模型标识

    private String description;//模型描述

    private String category;//模型分类

    

}
package com.lhtc.jv.service;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ModelQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.lhtc.jv.vo.ActModelVO;

/**
 * 流程模型service
 * @author www.wzbjsz.cn
 * @date 2019-01-21 11:28:38
 */
@Service
@Transactional(readOnly = true)
public class ActModelService {

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 创建模型
     * @param actModelVO
     * @return
     * @throws UnsupportedEncodingException
     */
    @Transactional(readOnly = false)
    public Model createModel(ActModelVO actModelVO) throws UnsupportedEncodingException{
        //初始化一个空模型
        Model model = repositoryService.newModel();
        model.setKey(actModelVO.getKey());
        model.setName(actModelVO.getName());
        model.setCategory(actModelVO.getCategory());
        model.setVersion(Integer.parseInt(String.valueOf(repositoryService.createModelQuery().modelKey(model.getKey()).count()+1)));

        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put(ModelDataJsonConstants.MODEL_NAME, model.getName());
        modelNode.put(ModelDataJsonConstants.MODEL_REVISION, model.getVersion());
        modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, actModelVO.getDescription());

        model.setMetaInfo(modelNode.toString());
        repositoryService.saveModel(model);

        //完善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.addModelEditorSource(model.getId(),editorNode.toString().getBytes("utf-8"));
        return model;
    }

    /**
     * 根据模型id查询
     * @param modelId 模型id
     * @return
     */
    public Model getModelById(String modelId){
        return repositoryService.getModel(modelId);
    }

    /**
     * 查询模型列表
     * @param pageable
     * @return
     */
    public Page<Model> getAllModels(Pageable pageable){
        ModelQuery modelQuery = repositoryService.createModelQuery().latestVersion().orderByLastUpdateTime().desc();
        return new PageImpl<>(modelQuery.listPage(pageable.getPageNumber()*pageable.getPageSize(), pageable.getPageSize()), pageable, modelQuery.count());
    }

    /**
     * 部署模型
     * @param modelId 模型id
     * @return
     * @throws IOException
     */
    @Transactional(readOnly = false)
    public List<ProcessDefinition> deployModel(String modelId) throws IOException{
        Model modelData = repositoryService.getModel(modelId);
        BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
        ObjectNode editorNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
        BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
        BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
        byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
        ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
        Deployment deployment = repositoryService.createDeployment().name(modelData.getName())
                .addInputStream(modelData.getKey()+".bpmn20.xml", in).enableDuplicateFiltering().deploy();
        return repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
    }

    /**
     * 删除模型
     * @param modelId 模型id
     */
    @Transactional(readOnly = false)
    public void deleteModel(String modelId){
        repositoryService.deleteModel(modelId);
    }

    /**
     * 导出模型xml文件
     * @param modelId 模型id
     * @param response HttpServletResponse
     * @throws IOException
     */
    public void exportModel(String modelId, HttpServletResponse response) throws IOException{
        Model modelData = repositoryService.getModel(modelId);
        BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
        ObjectNode editorNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
        BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
        BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
        byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
        ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
        IOUtils.copy(in, response.getOutputStream());
        String filename = bpmnModel.getMainProcess().getId() + ".bpmn20.xml";
        response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(filename, "UTF-8"));
        response.flushBuffer();
    }

}
package com.lhtc.jv.web.rest.activiti;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Optional;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.lhtc.jv.service.ActModelService;
import com.lhtc.jv.vo.ActModelVO;
import com.lhtc.jv.web.rest.util.HeaderUtil;
import com.lhtc.jv.web.rest.util.PaginationUtil;

import io.github.jhipster.web.util.ResponseUtil;

/**
 * 流程模型controller
 * @author www.wzbjsz.cn
 * @date 2019-01-21 13:39:47
 */
@RestController
@RequestMapping("/api")
public class ActModelResource {

    private final Logger log = LoggerFactory.getLogger(ActModelResource.class);

    private static final String ENTITY_NAME = "model";

    @Autowired
    private ActModelService actModelService;

    /**
     * 创建模型
     * @param actModelVO
     * @return the ResponseEntity with status 201 (Created) and with body the new model
     * @throws UnsupportedEncodingException
     * @throws URISyntaxException if the Location URI syntax is incorrect
     */
    @PostMapping("/models")
    public ResponseEntity<Model> createModel(@Valid @RequestBody ActModelVO actModelVO) throws UnsupportedEncodingException, URISyntaxException{
        log.debug("REST request to save Model : {}", actModelVO);
        Model result = actModelService.createModel(actModelVO);
        return ResponseEntity.created(new URI("/act/models/" + result.getId()))
                .headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
                .body(result);
    }

    /**
     * 根据模型id查询
     * @param modelId 模型id
     * @return
     */
    @GetMapping("/models/{modelId}")
    public ResponseEntity<Model> getModel(@PathVariable String modelId){
        log.debug("REST request to get Model : {}", modelId);
        return ResponseUtil.wrapOrNotFound(Optional.ofNullable(actModelService.getModelById(modelId)));
    }

    /**
     * 查询模型列表
     * @param pageable the pagination information
     * @return the ResponseEntity with status 200 (OK) and with body all models
     */
    @GetMapping("/models")
    public ResponseEntity<List<Model>> getAllModels(Pageable pageable) {
        final Page<Model> page = actModelService.getAllModels(pageable);
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/act/models");
        return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
    }

    /**
     * 部署模型
     * @param modelId 模型id
     * @return
     */
    @PutMapping("/models/deploy")
    public ResponseEntity<Void> deployModel(@RequestBody ActModelVO actModelVO){
        String modelId = actModelVO.getId();
        log.debug("REST request to deploy Model : {}", modelId);
        try {
            List<ProcessDefinition> processDefinitions = actModelService.deployModel(modelId);
            if(!CollectionUtils.isEmpty(processDefinitions)){
                return ResponseEntity.ok().headers(HeaderUtil.createAlert("A " + ENTITY_NAME + " is deployed with identifier " + modelId, modelId)).build();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(HeaderUtil.createFailureAlert(ENTITY_NAME, modelId,"A " + ENTITY_NAME + " failed to deploy with identifier " + modelId)).build();
    }

    /**
     * 删除模型
     * @param modelId 模型id
     * @return
     */
    @DeleteMapping("/models/{modelId}")
    public ResponseEntity<Void> deleteModel(@PathVariable String modelId) {
        log.debug("REST request to delete Model: {}", modelId);
        actModelService.deleteModel(modelId);
        return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, modelId)).build();
    }

    /**
     * 导出模型xml文件
     * @param modelId 模型id
     * @param response HttpServletResponse
     * @throws IOException
     */
    @GetMapping("/models/export")
    public void exportModel(@RequestParam("modelId")String modelId, HttpServletResponse response) throws IOException{
        actModelService.exportModel(modelId, response);
    }

}


 

  • 15
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 24
    评论
Activiti6最大的变化点就是对代码进行了重构,该版本修复以往的Bug并不多,但内部实现相对来说变化比较大。其突出的变化如下所示: 新增两款新引擎,Form引擎和DMN引擎(动态引擎)。其DMN引擎允许开发人员创建自己的决策表。可以通过变量和定义的规则方式从决策表计算结果。这些决策表的数据可以被rule task调用,决策表与流程实例是完全隔离的,相互之间不需要知道对方的存在。Form引擎可以通过Activiti6 UI界面进行配置,通俗一点的理解就是Activiti6将Form表单独立出来了。Form表单信息可以以JSON格式进行定义和使用。Activiti6 UI 默认包括新的规则引擎和表单引擎。 新增ad-hoc子流程。可以参考文章(ad-hoc子流程使用)。 作业执行器被重构。Activiti6版本仅保留了Activiti5版本的异步作业执行器(async executor)。定时作业被划分了四个不同的表:executable jobs, timer jobs, suspended jobs 和deadletter jobs。引擎可以更快的执行作业。定时器作业在新的版本存储于单独的表,一个线程会定时轮训需要执行的作业,快到期的作业会被添加到suspended jobs表。重试的作业已经被干掉了,需要重试的作业会被添加到deadletter jobs表。这样的重构意义主要是为了提高查询效率,可以执行的作业可以很快的被查询出来。 作业执行器通过消息队列的方式进行,关于这一点可以参考随后的文章。 瞬态变量的引入。瞬态变量不会存储到 Activiti 变量表,但仍为单一的事务持续时间执行。比如可以在REST服务之间进行调用的时候使用,或者使用于Java service task。 引入了事务依赖监听器,可以参考Activiti依赖事务监听器(上)的讲解。 Activiti 6 UI 程序,添加了DMN编辑器。 对于多实例节点而言,添加了终止多实例节点的相关方法。这个特性允许开发人员使用API结束多实例所有节点的执行。 优化补偿活动行为和在子流程的使用。 在运行流程实例以及执行实例添加了开始时间以及启动流程实例的人字段。在ru_task增加了任务的认领时间(claim time)。 妥善解决数据库架构 (oracle/postgres) 的使用。 修复历史数据捕获。 大量重构 Activiti 6 UI 应用程序,例如应用程序定义现在部署作为正常的活动部署,没有为其单独的应用程序定义表。 改进Activiti 6 QA的问题。
### 回答1: Spring Boot可以很方便地与Activity进行集成Activity是一个开源的工作流引擎,可以帮助开发人员设计和执行复杂的业务流程。以下是Spring Boot整合Activity的步骤: 1. 添加Activity的依赖 在pom.xml文件添加以下依赖: ``` <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>6..</version> </dependency> ``` 2. 配置Activityapplication.properties文件添加以下配置: ``` # 数据库配置 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=root # Activity配置 spring.activiti.database-schema-update=true spring.activiti.check-process-definitions=false ``` 3. 创建流程定义 在resources目录下创建一个名为processes的文件夹,用于存放流程定义文件。在该文件夹下创建一个名为myProcess.bpmn20.xml的文件,用于定义一个简单的流程。 4. 编写业务代码 在业务代码使用Activity的API来启动流程、查询任务、完成任务等操作。 以上就是Spring Boot整合Activity的基本步骤。通过这种方式,我们可以很方便地使用Activity来管理业务流程,提高开发效率和业务处理能力。 ### 回答2: Spring Boot是一个开源的Java开发框架,能够简化Spring应用程序的开发和部署。它提供了许多内置功能和开箱即用的配置,使得我们能够更快地构建和部署应用程序。而Activiti是一个开源的工作流引擎,它提供了一种轻量级和灵活的方式来管理和执行业务流程。 将Spring Boot与Activiti整合可以使我们更方便地使用工作流引擎来管理业务流程。首先,我们需要在pom.xml文件添加相应的依赖。然后,我们可以创建一个配置类,使用@EnableActiviti注解来启用Activiti的相关功能。 在整合过程,我们可以使用Spring的依赖注入来管理Activiti的各种服务和组件。例如,我们可以注入RuntimeService来启动一个新的流程实例,注入TaskService来管理任务,注入HistoryService来查询历史数据等等。 另外,Spring Boot还提供了一些自动配置的功能,使得我们能够更快地配置和使用Activiti。例如,它可以自动创建和初始化Activiti的数据库表结构,而不需要手动去执行SQL脚本。此外,我们还可以使用Spring Boot的配置文件来配置Activiti的相关参数,如数据库连接信息、流程定义文件等等。 总的来说,将Spring Boot与Activiti整合可以帮助我们更方便地开发和部署业务流程。它提供了一种简单、灵活和高效的方式来管理和执行业务流程,使得我们能够更好地提高业务的效率和质量。因此,Spring Boot整合Activiti是一个非常有价值和推荐的组合。 ### 回答3: Spring Boot是一个用于构建微服务和快速开发的框架,它提供了很多方便的特性和功能。Activity是一个用于管理和执行业务流程的框架。那么如何将Spring Boot与Activity整合呢? 首先,需要在Spring Boot项目添加Activity的依赖。可以通过在pom.xml文件添加如下依赖来引入Activity: ```xml <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>6.0.0</version> </dependency> ``` 添加完依赖后,需要配置Activity的相关属性。在application.properties(或application.yml)文件添加以下配置: ```properties spring.activiti.database-schema-update=true spring.activiti.async-executor-activate=true spring.activiti.job-executor-async=true ``` 这些配置可以根据具体需求进行调整。 然后,在Spring Boot项目创建一个继承自`org.activiti.spring.boot.SecurityAutoConfiguration`的配置类,并添加相关的注解。例如: ```java @Configuration @EnableAutoConfiguration public class ActivityConfiguration extends SecurityAutoConfiguration { // 添加Activity的相关配置或自定义代码 } ``` 最后,可以在Spring Boot的控制器调用Activity的API或使用Activity的注解来执行业务流程。例如: ```java @RestController public class MyController { @Autowired private ProcessRuntime processRuntime; @PostMapping("/startProcess") public void startProcess() { processRuntime.start(ProcessPayloadBuilder .start() .withProcessDefinitionKey("myProcess") .build()); } // 其他方法 } ``` 这样就完成了Spring Boot与Activity的整合。通过这种整合,可以在Spring Boot项目方便地使用Activity的功能,实现业务流程的管理和执行。同时,Spring Boot的自动配置和便利特性也可以为Activity的使用提供很多便利。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值