Activiti6.0+springboot,流程图绘制,在线设计器,activiti-explorer整合modeler

       前言

        最近公司让接收一个审批相关的项目,于是想到就用activiti工作流来处理,下面着重介绍一下activiti6.0整合springboot,以及一些常用的activiti java api的使用,比较实用,都是能够直接拷贝开干的方法。

        首先,建议看一下actitivi官网上,有个基础的了解。

        先说一下实现的效果,要做到能够通过官网提供的流程图demo设置修改流程,然后发布。然后后台通过各种操作去玩儿流程。

Activiti6.0+springboot,流程图绘制,在线设计器,activiti-explorer整合modeler_第1张图片

1.整合springboot

       好了,开始整合springboot。

        1.1pom



	4.0.0
	
		org.springframework.boot
		spring-boot-starter-parent
		2.3.9.RELEASE
		 
	
	com.ht
	activiti_springboot
	0.0.1-SNAPSHOT
	activiti_springboot
	activiti-springboot

	
		1.8
		6.0.0
		5.23.0
	

	
		
			org.springframework.boot
			spring-boot-starter-web
		
		
			org.springframework.boot
			spring-boot-starter-test
			test
		
		
			org.slf4j
			slf4j-api
			1.7.21
		
		
			org.slf4j
			slf4j-log4j12
			1.7.21
		
		
			com.h2database
			h2
			1.4.193
		
		
			org.springframework.boot
			spring-boot-starter-thymeleaf
		
		
			org.projectlombok
			lombok
			1.18.20
			provided
		
		
		
			org.activiti
			activiti-spring-boot-starter-basic
			${activiti.version}
		
		
			org.activiti
			activiti-json-converter
			${activiti.version}
		

		
			mysql
			mysql-connector-java
			5.1.41
		

		
			commons-io
			commons-io
			2.10.0
		

		
			org.apache.xmlgraphics
			batik-transcoder
			1.10
		

		
			org.apache.xmlgraphics
			batik-codec
			1.9
		

	

	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
				2.3.9.RELEASE
			
		
	


        1.2前端画图工具整合

        首先需要下载activiti-explorer.war(这个war包是官方给的demo)。这里后面我会给出源码,源码里面也有。

        Activiti6.0+springboot,流程图绘制,在线设计器,activiti-explorer整合modeler_第2张图片

        上图就是,我们在activiti-explorer.war包中需要的东西,stencilset.json是汉化包。

        需要修改app-cfg.js,这里是为了让画图工具调用你自己的controller。

Activiti6.0+springboot,流程图绘制,在线设计器,activiti-explorer整合modeler_第3张图片

        1.3基础方法支持

        修改好后,需要重写一些基础的方法来支持流程图的编辑和保存,ModelEditorJsonRestResource类中的getEditorJson方法根据modelId来支持获取流程图的json串。

@RestController
@RequestMapping("service")
public class ModelEditorJsonRestResource implements ModelDataJsonConstants {
    protected static final Logger LOGGER = LoggerFactory.getLogger(ModelEditorJsonRestResource.class);
    @Resource
    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类中的save方法用于保存编辑流程图

@RestController
@RequestMapping("service")
public class ModelSaveRestResource implements ModelDataJsonConstants {

    protected static final Logger LOGGER = LoggerFactory.getLogger(ModelSaveRestResource.class);

    @Resource
    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);
        }
    }
}

        还需要一个StencilsetRestResource类的stencilset方法,这些方法都可以在集成好的画图工具页面f12看到,都是一些必须的方法。

@RestController
@RequestMapping("service")
public class StencilsetRestResource {

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

        1.4 yml文件

server:
    port: 9999

spring:
    application:
        name: activiti-springboot
    datasource:
        url: xxx
        username: xxx
        password: xxx
        driver-class-name: com.mysql.jdbc.Driver
    activiti:
        database-schema-update: true
        # 自动部署验证设置:true-开启(默认)、false-关闭
        check-process-definitions: false
    thymeleaf:
        mode: LEGACYHTML5
        cache: false
logging:
    level:
        org.activiti.engine.impl.persistence.entity: debug

2.初始化流程

        2.1 创建流程

        通过单元测试创建一个流程,得到流程的modelId

@Test
    public void createModel() throws UnsupportedEncodingException {
        Model model = repositoryService.newModel();
        //设置默认流程名称
        String name = "TEST";
        String description = "";
        int revision = 1;
        //设置key
        String key = "TEST-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();
        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"));
        //得到modelid
        System.out.println(id);
    }

        如果是第一次集成,运行项目之后,activiti对应的表会自动创建,很方便。流程创建成功后,可以看到对应的表与对应的记录已经生成,我这里modeId为1.

        Activiti6.0+springboot,流程图绘制,在线设计器,activiti-explorer整合modeler_第4张图片

       2.2 editor controller

        建立一个editor controller用于访问画图工具的页面

@Controller
public class ModelerController {
    @GetMapping("editor")
    public String editor() {
        return "/modeler";
    }
}

        2.3 启动项目访问页面

        启动项目后访问页面http://localhost:9999/editor?modelId=1,这里modelId就是上面单元测试产生的modelId,可以如果可以看到画图的页面并且左侧事件以及顶部工具栏,那么就成功了。

        初次访问该流程右边的为空白,这个流程图是我自己画的。

Activiti6.0+springboot,流程图绘制,在线设计器,activiti-explorer整合modeler_第5张图片

        2.4 保存流程图

        如果是第一次接触activiti的小伙伴们肯定看到左侧的一系列的事件列表等等可能比较懵。我第一次看也是完全处于懵逼状态,这里建议可以去看一下https://docs.awspaas.com/reference-guide/aws-paas-process-reference-guide/appendix/process_model_version_control.html这个网址,里面有对BPMN2的详细讲解,看完会有一个不错的理解。

        好了,现在可以来画属于自己的流程图啦!一顿操作之后,点击左上角保存按钮,会弹出一个保存模型框,点击保存就可以了。刷新页面可以看到流程已经保存成功。

        Activiti6.0+springboot,流程图绘制,在线设计器,activiti-explorer整合modeler_第6张图片

        好了,写到这里,我项目目前也只搭建了这么一点,activiti与springboot的初步整合就已经完成了。

        这只是第一步,后续我会再发一篇对activiti流程详细操作教程。都是工作上能够用到,自己摸索加上google的。也会基于上面我画的那个流程图对各种activiti的java api做个讲解,会涉及到基础的操作,以及退回等等稍微复杂一些的操作,基本上能够覆盖公司开发的需求。

        详细的一些对于activiti的操作我写了另外一篇文章,也给出了源码,有兴趣的可以看看https://blog.csdn.net/a771664696/article/details/118358296

你可能感兴趣的:(activiti,activiti工作流,activiti,spring,boot)