2016.3.23 集成新版activiti-modeler(5.17+)到项目中
书:《activiti实战》
博客:
http://www.kafeitu.me/activiti/2013/03/10/integrate-activiti-modeler.html
http://www.kafeitu.me/activiti/2015/12/27/integrate-new-activiti-modeler-and-rest.html
http://blog.sina.com.cn/s/blog_bca2afff0102wrjk.html
首先按书中所说办法集成,里面的内容和博客(第一个)地址一致。但是没有注意它集成的是5.16,即旧版。但是我复制的一些文件是github中的最新版,所以造成了一些奇怪的问题。
然后搜索后,发现书的作者在15年又更新了一篇博客(第二个),针对新版5.17+的modeler集成。但是在这篇博客中,复制的文件包含了explorer的源代码,觉得不好。
搜索后,又联合参考了第三个博客。
总结:比对了许多博客,也试过几个方法,最后懂了每一步在做什么之后,就容易多了。
ps:在《activiti实战》中,作者提到集成activiti-modeler依赖activiti-rest,但是我没做activiti-rest的集成,也成功了,所以它到底依赖哪里?
集成后的效果:
访问路径: http://localhost:8080/项目名/editor-app所在文件夹路径/modeler.html?modelId=XX (前提是这个model已经创建好了)
项目总结构:
步骤简要概述:
1 在pom.xml中添加依赖 2 修改web.xml 3 修改applicationContext.xml(与spring相关的配置) 4 修改applicationContext-workflow.xml(与activiti相关的配置) 5 新增applicationContext-mvc-modeler.xml(与activiti-modeler相关的配置) 6 在webapp下新建文件夹designer,复制activiti-explorer的editor-app与modeler.html到此路径下。 7 复制explorer的stencilset.json到resources路径下。 8 在controller文件夹下新建ModelController.java,用来测试集成效果。
1.pom.xml
只列出与activiti相关的。
1 版本号 5.22.0 2 activiti-spring 3 activiti-modeler 4 activiti-diagram-rest 5 activiti-explorer 6 java-uuid-generator
其中的java-uuid-generator,没有在一篇博客中看到需要加这个依赖。但是我运行时总是提示缺少java.uuid,项目启动失败。搜索后我自己加了这个依赖,于是就不再报异常了。
<!-- activiti 与 Spring 集成 --> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring</artifactId> <version>${activiti.version}</version> </dependency> <!-- activiti 设计器集成 --> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-modeler</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-explorer</artifactId> <version>${activiti.version}</version> </dependency> <dependency> <groupId>com.fasterxml.uuid</groupId> <artifactId>java-uuid-generator</artifactId> <version>3.1.4</version> </dependency>
2.web.xml
配置modeler的servlet。其中路径/service/* 很重要。和后面修改的app.cfg.js文件有对应关系。所以一定要匹配(不一定要取名service)。
1 <servlet> 2 <servlet-name>ModelRestServlet</servlet-name> 3 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 4 <init-param> 5 <param-name>contextConfigLocation</param-name> 6 <param-value> 7 classpath:/spring/**/applicationContext-mvc-modeler.xml 8 </param-value> 9 </init-param> 10 <load-on-startup>1</load-on-startup> 11 </servlet> 12 <servlet-mapping> 13 <servlet-name>ModelRestServlet</servlet-name> 14 <url-pattern>/service/*</url-pattern> 15 </servlet-mapping>
3.applicationContext.xml
1 <context:component-scan 2 base-package="org.activiti.rest.editor"> 3 <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> 4 </context:component-scan> 5 6 <import resource="classpath:spring/framework/applicationContext-workflow.xml"/>
4.applicationContext-workflow.xml
1 <!--原来就有的一些配置不再提,比如processEngine--> 2 <!-- 单例json对象 --> 3 <bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper"/> 4 5 <!-- 引擎内部提供的UUID生成器,依赖fastxml的java-uuid-generator模块 --> 6 <bean id="uuidGenerator" class="org.activiti.engine.impl.persistence.StrongUuidGenerator" />
5.applicationContext-mvc-modeler.xml
1 <!-- 自动扫描且只扫描@Controller --> 2 <context:component-scan base-package="org.activiti.rest.editor,org.activiti.rest.diagram"> 3 <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> 4 </context:component-scan> 5 6 <mvc:annotation-driven/>
6.复制文件
先从Github下载官方Activiti源码,地址:https://github.com/Activiti/Activiti。
源码目录(如果是zip下载请先解压缩)中找到modules/activiti-webapp-explorer2/src/main子目录。去webapp里和resources里去找要复制的那三个文件。
但是我进入这个目录,根本没有editor-app、modeler.html、stencilset.json? 连webapp和resources路径都没有??
于是我就直接复制了kafeitu的项目里的这三个文件。(版本也是5.22.0)
复制完后,修改designer/editor-app/app-cfg.js文件,把根路径修改为:项目名/ModelServlet定义的映射路径。
ACTIVITI.CONFIG = {
'contextRoot' : '/wfs_web/service',
};
7.创建model
(1)Model.jsp与Model.js
1 <!DOCTYPE html> 2 <%@ page contentType="text/html; charset=UTF-8" %> 3 <html> 4 <head> 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 6 <title>流程任务管理</title> 7 8 </head> 9 <body> 10 <%@ include file="/bxui/bxuihead.jsp" %> 11 <script type="text/javascript" 12 src="<%=toolkitPath%>/bxui/baosight-require.js"></script> 13 <script type="text/javascript" 14 src="<%=toolkitPath%>/workflow/model.js"></script> 15 <link rel="stylesheet" 16 href="<%=toolkitPath%>/bxui/other/css/style-frame-inner.css"/> 17 18 19 <div class="col-sm-3 col-xs-3" style="margin-top: 5px"> 20 <button class="btn btn-sm pull-right btn-block" 21 onclick="createModel();"> 22 <div class="ace-icon fa fa-search"></div> 23 <span>createModel</span> 24 </button> 25 </div> 26 <div class="col-sm-3 col-xs-3" style="margin-top: 5px"> 27 <button class="btn btn-sm pull-right btn-block" 28 onclick="deleteModel();"> 29 <div class="ace-icon fa fa-trash-o"></div> 30 <span>deleteModel</span> 31 </button> 32 </div> 33 <div class="col-sm-3 col-xs-3" style="margin-top: 5px"> 34 <button class="btn btn-sm pull-right btn-block" 35 onclick="viewModel();"> 36 <div class="ace-icon fa fa-search"></div> 37 <span>createModel</span> 38 </button> 39 </div> 40 <div class="col-sm-3 col-xs-3" style="margin-top: 5px"> 41 <button class="btn btn-sm pull-right btn-block" 42 onclick="updateModel();"> 43 <div class="ace-icon fa fa-trash-o"></div> 44 <span>deleteModel</span> 45 </button> 46 </div> 47 48 </body> 49 </html>
1 function createModel() { 2 alert("createModel"); 3 var paramJsonObj = new Object(); 4 paramJsonObj.name = "name"; 5 paramJsonObj.key = "key"; 6 paramJsonObj.description = "description"; 7 8 var callback = { 9 onSuccess: function() { 10 alert("onSuccess"); 11 } 12 }; 13 AjaxCommunicator.ajaxRequest('/workflow/model.do?method=create', 'POST', paramJsonObj, callback); 14 }
点击button时会访问路径:
AjaxCommunicator.ajaxRequest('/workflow/model.do?method=create', 'POST', paramJsonObj, callback);
(2)ModelController
新建模型并跳转到模型设计器。
1 /** 2 * 流程模型控制器 3 * Created by liyuhui on 2017/3/15. 4 */ 5 @Controller 6 @RequestMapping("/wfs_web/model.do") 7 public class ModelController { 8 9 protected Logger logger = LoggerFactory.getLogger(getClass()); 10 11 @Autowired 12 private RepositoryService repositoryService; 13 @Autowired 14 private HttpServletRequest request; 15 @Autowired 16 private HttpServletResponse response; 17 18 19 /** 20 * 测试页面 21 */ 22 @RequestMapping(value = "") 23 public ModelAndView init(HttpServletRequest request, 24 HttpServletResponse response) { 25 return new ModelAndView("/wfs/model"); //访问wfs目录下的model.jsp 26 } 27 28 /** 29 * 创建模型 30 */ 31 @RequestMapping(params = "method=create", method = RequestMethod.POST) 32 public void create(String ajaxParam) { 33 try { 34 JSONObject ajaxParamObj = JSONObject.parseObject(ajaxParam); 35 String name = ajaxParamObj.getString("name"); 36 String description = ajaxParamObj.getString("description"); 37 String key = ajaxParamObj.getString("key"); 38 39 ObjectMapper objectMapper = new ObjectMapper(); 40 ObjectNode modelObjectNode = objectMapper.createObjectNode(); 41 modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, name); 42 modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1); 43 modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, StringUtils.defaultString(description)); 44 45 Model newModel = repositoryService.newModel(); 46 newModel.setMetaInfo(modelObjectNode.toString()); 47 newModel.setName(name); 48 newModel.setKey(StringUtils.defaultString(key)); 49 repositoryService.saveModel(newModel); 50 51 ObjectNode editorNode = objectMapper.createObjectNode(); 52 editorNode.put("id","canvas"); 53 editorNode.put("resourceId","canvas"); 54 55 ObjectNode stencilSetNode = objectMapper.createObjectNode(); 56 stencilSetNode.put("namespace","http://b3mn.org/stencilset/bpmn2.0#"); 57 editorNode.put("stencilset",stencilSetNode); 58 59 //为模型绑定参数 60 repositoryService.addModelEditorSource(newModel.getId(), editorNode.toString().getBytes("utf-8")); 61 62 //打开模型设计器页面 63 String a = request.getContextPath(); //wfs_web 64 response.sendRedirect(request.getContextPath() + "/designer/modeler.html?modelId=" + newModel.getId()); 65 66 } catch (Exception e) { 67 logger.error("创建模型失败:", e); 68 } 69 } 70 }
(3)测试
输入http://localhost:8080/wfs_web/model.do,跳转到model.jsp页面。
点击createModel那个button,进入ModelController里的create方法。
执行完saveModel,数据库中表act_re_model多了一条信息:
然后重定向到路径:http://localhost:8080/wfs_web/designer/modeler.html?modelId=30007,成功打开设计器页面,并且可以进行操作。
因为editor-app复制到了webapp下的designer文件夹,所以路径要加上designer。
至此,集成成功,model的增删改查其他代码,可以参看咖啡兔的博客和代码。