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;}@Overridepublic 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;}@Overridepublic 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 outputByteArrayOutputStream outStream = new ByteArrayOutputStream();TranscoderOutput output = new TranscoderOutput(outStream);// Do the transformationtranscoder.transcode(input, output);final byte[] result = outStream.toByteArray();repositoryService.addModelEditorSourceExtra(model.getId(), result);outStream.close();//...}
ModelSaveRestResource
类用于modeler.html
保存
新建模型
创建按钮对应的后台逻辑
modeler.html 关闭按钮/保存退出按钮跳转路径设置
EditorProcessDefinitionDetailPanel.java
新建模型、导入、编辑模型、复制模型、删除模型、部署、导出模型 按钮(下拉列表)添加事件监听