Activiti 工作流引擎 ~ 官方demo学习

本文详细介绍了Activiti工作流引擎5.22.0版本的官方demo学习,包括其使用Vaadin作为前端框架,展示了如何解压和理解demo的文件结构,如modeler.html、属性配置文件、Spring配置文件等。还探讨了关键类的作用,如用于初始化数据、配置对象以及模型的编辑和保存。文章涵盖了新建、编辑、部署、导出模型等操作的后台逻辑和事件监听设置。

Activiti 工作流引擎 官方demo学习

本文使用的Activiti版本为5.22.0

Activiti 官方网站

Activiti-5.22.0 源码

Vaadin 官方网站

Vaadin Web应用开发教程(3):Vaadin应用程序框架介绍

Activiti 官方demo中使用Vaadin作为前端框架进行页面展示

Activiti 官方下载的文件目录如下,在wars文件夹中提供了两个demo
这里写图片描述

解压activiti-explorer.war,文件结构如下
这里写图片描述

modeler.html是Activiti Modeler的编辑界面,如图:
这里写图片描述

属性配置文件
日志属性:log4j.properties
引擎属性:engine.properties
数据库属性:db.properties
ui.properties

spring配置文件
activiti-custom-context.xml
activiti-login-context.xml
activiti-ui-context.xml

org.activiti.explorer.conf java配置文件
这里写图片描述

org.activiti.explorer.servlet servlet文件
这里写图片描述

对应的java文件可以在源码中找到
这里写图片描述

web.xml

<listener>
    <listener-class>org.activiti.explorer.servlet.WebConfigurer</listener-class>
</listener>

WebConfigurer.java

public class WebConfigurer implements ServletContextListener {

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

  public AnnotationConfigWebApplicationContext context;

  public void setContext(AnnotationConfigWebApplicationContext context) {
    this.context = context;
  }

  @Override
  public void contextInitialized(ServletContextEvent sce) {
    ServletContext servletContext = sce.getServletContext();

    log.debug("Configuring Spring root application context");

    AnnotationConfigWebApplicationContext rootContext = null;

    if (context == null) {
        rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(ApplicationConfiguration.class);
        rootContext.refresh();
    } else {
        rootContext = context;
    }

    servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, rootContext);

    initSpring(servletContext, rootContext);

    log.debug("Web application fully configured");
  }

  /**
   * Initializes Spring and Spring MVC.
   */
  private ServletRegistration.Dynamic initSpring(ServletContext servletContext, AnnotationConfigWebApplicationContext rootContext) {
    log.debug("Configuring Spring Web application context");
    AnnotationConfigWebApplicationContext dispatcherServletConfiguration = new AnnotationConfigWebApplicationContext();
    dispatcherServletConfiguration.setParent(rootContext);
    dispatcherServletConfiguration.register(DispatcherServletConfiguration.class);

    log.debug("Registering Spring MVC Servlet");
    ServletRegistration.Dynamic dispatcherServlet = servletContext.addServlet("dispatcher", new DispatcherServlet(dispatcherServletConfiguration));
    dispatcherServlet.addMapping("/service/*");
    dispatcherServlet.setLoadOnStartup(1);
    dispatcherServlet.setAsyncSupported(true);

    return dispatcherServlet;
  }

  @Override
  public void contextDestroyed(ServletContextEvent sce) {
    log.info("Destroying Web application");
    WebApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext());
    AnnotationConfigWebApplicationContext gwac = (AnnotationConfigWebApplicationContext) ac;
    gwac.close();
    log.debug("Web application destroyed");
  }
}

contextInitialized()

rootContext.register(ApplicationConfiguration.class);

initSpring()

AnnotationConfigWebApplicationContext dispatcherServletConfiguration = new AnnotationConfigWebApplicationContext();
dispatcherServletConfiguration.setParent(rootContext);
dispatcherServletConfiguration.register(DispatcherServletConfiguration.class);

ServletRegistration.Dynamic dispatcherServlet = servletContext.addServlet("dispatcher", new DispatcherServlet(dispatcherServletConfiguration));
dispatcherServlet.addMapping("/service/*");
dispatcherServlet.setLoadOnStartup(1);

ApplicationConfiguration.java

@Configuration
@PropertySources({
  @PropertySource(value = "classpath:db.properties", ignoreResourceNotFound = true),
  @PropertySource(value = "classpath:engine.properties", ignoreResourceNotFound = true)
})
@ComponentScan(basePackages = { "org.activiti.explorer.conf" })
@ImportResource({"classpath:activiti-ui-context.xml", "classpath:activiti-login-context.xml", "classpath:activiti-custom-context.xml"})
public class ApplicationConfiguration {

}

activiti-custom-context.xml文件中的内容是被注释掉了,官方activiti-explorer demo 中利用org.activiti.explorer.conf.ActivitiEngineConfiguration.java文件进行了配置

DemoDataConfiguration.java文件用于初始化demo数据
JacksonConfiguration.java文件用于配制com.fasterxml.jackson.databind.ObjectMapper对象,activiti内部依赖于该对象

DispatcherServletConfiguration.java

@ComponentScan({"org.activiti.rest.editor", "org.activiti.rest.diagram"})
@EnableAsync
public class DispatcherServletConfiguration extends WebMvcConfigurationSupport {
    //...
}

这里写图片描述

StencilsetRestResource.java

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

StencilsetRestResource类读取stencilset.json用于modeler.html初始化

ModelEditorJsonRestResource.java

@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 (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);
        //...
    return modelNode;
  }

ModelEditorJsonRestResource类获取模型数据用于在modeler.html中编辑模型

ModelSaveRestResource.java

@RequestMapping(value="/model/{modelId}/save", method = RequestMethod.PUT)
  @ResponseStatus(value = HttpStatus.OK)
  public void saveModel(@PathVariable String modelId, @RequestBody MultiValueMap<String, String> values) {
      //...
      Model model = repositoryService.getModel(modelId);

      ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());

      modelJson.put(MODEL_NAME, values.getFirst("name"));
      modelJson.put(MODEL_DESCRIPTION, values.getFirst("description"));
      model.setMetaInfo(modelJson.toString());
      model.setName(values.getFirst("name"));

      repositoryService.saveModel(model);

      repositoryService.addModelEditorSource(model.getId(), values.getFirst("json_xml").getBytes("utf-8"));

      InputStream svgStream = new ByteArrayInputStream(values.getFirst("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();
      //...

  }

ModelSaveRestResource类用于modeler.html保存

这里写图片描述

这里写图片描述

新建模型
这里写图片描述
创建按钮对应的后台逻辑
这里写图片描述

modeler.html 关闭按钮/保存退出按钮跳转路径设置
这里写图片描述
这里写图片描述

这里写图片描述
EditorProcessDefinitionDetailPanel.java
这里写图片描述
新建模型、导入、编辑模型、复制模型、删除模型、部署、导出模型 按钮(下拉列表)添加事件监听

这里写图片描述
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值