转载请注明源地址:http://www.cnblogs.com/lighten/p/5878169.html

  接上一章,activiti工作流引擎虽然运行了起来,但是什么都没有。activiti官方在其安装包中是给了两个war的demo包的,一个是activiti-explorer.war,一个是activiti-rest.war。第一个就是用在web端对activiti工作流引擎的一个展示,可以看到具体内容。第二个是对activiti提供的rest接口的一个demo。这两个war包可以放入tomcat的webapp文件夹中,启动tomcat即可。explorer项目可以访问http://localhost:8080/activiti-explorer地址就可以管理工作流引擎了。账号默认有三个:

  第二个rest项目是没有界面的,可以写个ajax的工具来完成对activiti的rest接口测试。这两个war包的源代码都是能在activiti在github上的开源中找到的,在/modules/activiti-webapp-explorer2和/modules/activiti-webapp-rest2。这两个就是其源代码。

  explorer不仅是对activiti工作流的一个展示,可以查看和进行相关的操作,还集成了Activiti Modeler。Activiti Modeler是一个在线流程设计器,可以让业务人员用画图的方式自己设计定义工作流,并部署到工作流引擎中。Activiti Modeler采取的是LGPL 2.1的开源协议。explorer是官方给出的一个管理demo,这个应该是不能商用的,Activiti Modeler这个模块是可以的,但是要遵守相关的开源协议要求。下面介绍如何整合Activiti Modeler到自己的项目之中:

  从github中将activiti下载下来,解压,进入/modules/activiti-webapp-explorer2文件夹。

   src/main/webapp/editor-app 将editor-app文件夹拷贝到自己的项目中的相同位置,这个文件夹放置了在线流程设计器的相关HTML、CSS、JS和图片等资源

   src/main/webapp/modeler.html 将modeler.html这个文件也拷贝到webapp下,这是在线流程设计器的主页

   src/main/resources/stencilset.json 将这个json文件拷贝到resources文件夹下,其定义了bpmn的相关构成组件的信息,之后会介绍

   现在运行项目,直接访问地址:http://localhost:端口号/项目名/modeler.html 会发现只有一个布局,各种功能及组件都没有显示出来,F12查看发现访问在线流程编辑器主页的时候会发现其访问了http://localhost:端口号/activiti-explorer/service/model//json 这个地址,实际上我现在还没有写后台。这说明了两个问题:一是前台页面应该是写死了url的。二是activiti应该有与之对应的jar包完成Activiti Modeler与个人项目的整合。

  先查找前台页面会发现在editor-app文件夹下的app-cfg.js中全局访问路径/activiti-explorer/service 将activiti-explorer改成自己的项目名service路径会在web.xml中配置,可以更改。这个http://localhost:端口号/activiti-explorer/service/model//json 实际的调用地方在app.js中的一个方法中:

  1. /* Helper method to fetch model from server (always needed) */
  2. function fetchModel(modelId) {
  3.  
  4. var modelUrl = KISBPM.URL.getModel(modelId);
  5.  
  6. $http({method: 'GET', url: modelUrl}).
  7. success(function (data, status, headers, config) {
  8. $rootScope.editor = new ORYX.Editor(data);
  9. $rootScope.modelData = angular.fromJson(data);
  10. $rootScope.editorFactory.resolve();
  11. }).
  12. error(function (data, status, headers, config) {
  13. console.log('Error loading model with id ' + modelId + ' ' + data);
  14. });
  15. }

  断点截图:

  第二个问题实际上Activiti Modeler的后台服务官方是给出了的,都放在了activiti-modeler.jar包中,其采用的是spring-mvc的形式。所以在pom.xml中添加相关依赖:

  1. <dependency>
  2. <groupId>org.activiti</groupId>
  3. <artifactId>activiti-modeler</artifactId>
  4. <version>5.21.0</version>
  5. </dependency>

  查看activiti-modeler源码,发现里面十分简单,一共只有三个类,对应着三个URL,分别是:

  /editor/stencilset 用来加载并返回stencilset.json文件的内容

  /model/{modelId}/json 这个就是访问的那个url了,通过部署的modelId模型编辑源

  /model/{modelId}/save 这个是用来保存编辑的模型

  知道这些之后,我们再在resources文件夹下创建一个spring-mvc-modeler.xml用于提供对Activiti Modeler后台URL的支持。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:mvc="http://www.springframework.org/schema/mvc"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/context
  9. http://www.springframework.org/schema/context/spring-context.xsd
  10. http://www.springframework.org/schema/mvc
  11. http://www.springframework.org/schema/mvc/spring-mvc.xsd">
  12.  
  13. <!-- mvc中只扫controller层,而modeler模块也只有controller层-->
  14. <context:component-scan base-package="org.activiti.rest.editor">
  15. <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  16. </context:component-scan>
  17.  
  18. <!-- modeler需要自动注入ObjectMapper -->
  19. <bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper"/>
  20.  
  21. <mvc:annotation-driven />
  22. </beans>

  在web.xml中配置路径分发:

  1. <servlet>
  2. <servlet-name>ModelerServlet</servlet-name>
  3. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  4. <init-param>
  5. <param-name>contextConfigLocation</param-name>
  6. <param-value>classpath:spring-mvc-modeler.xml</param-value>
  7. </init-param>
  8. <load-on-startup>1</load-on-startup>
  9. </servlet>
  10. <servlet-mapping>
  11. <servlet-name>ModelerServlet</servlet-name>
  12. <!-- url要与app-cfg.js中配置的一致 -->
  13. <url-pattern>/service/*</url-pattern>
  14. </servlet-mapping>

  配置完成后,启动项目不会报错,但是访问依旧是404not found,/项目名/service/model//json 查看后台,方法没有被执行,这个可能是少了中间的参数,url没有匹配。先看前台url配置。url是配置在了configuration文件夹下的url-config中。继续查找源码,看是哪里调用了这个方法,在app.js中发现:

  1. /**
  2. * Initialize the Oryx Editor when the content has been loaded
  3. */
  4. $rootScope.$on('$includeContentLoaded', function (event) {
  5. if (!$rootScope.editorInitialized) {
  6.  
  7. ORYX._loadPlugins();
  8.  
  9. var modelId = EDITOR.UTIL.getParameterByName('modelId');
  10. fetchModel(modelId);
  11. ...
  12. }

  EDITOR.UTIL.getParameterByName('modelId'),查找源码在editor-utils.js中找到这块代码:

  1. getParameterByName: function (name) {
  2. name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
  3. var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
  4. results = regex.exec(location.search);
  5. return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  6. },

  这样就很明显了,在访问这个界面的时候要带上查询参数,必须访问地址http://localhost:端口号/项目名/modeler.html?modelId=xx。这样查询的url就是/model/xx/json了。但是这样之后还是报错404,这回要看后台是否哪里配置有问题了。

   查看后台日志,发现里面的方法是被执行了,这证明URL是匹配上了。日志提示了下面一段话:org.springframework.web.servlet.DispatcherServlet.noHandlerFound(1120) | No mapping found for HTTP request with URI [/activiti-spring/service/model/1/model/1/json] in DispatcherServlet with name 'ModelerServlet'。这就相当于url前面多了model/1/这段。查看源码,断点调试:

  1. @RequestMapping(value="/model/{modelId}/json", method = RequestMethod.GET, produces = "application/json")
  2. public ObjectNode getEditorJson(@PathVariable String modelId) {
  3. ObjectNode modelNode = null;
  4.  
  5. Model model = repositoryService.getModel(modelId);
  6.  
  7. if (model != null) {
  8. try {
  9. if (StringUtils.isNotEmpty(model.getMetaInfo())) {
  10. modelNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
  11. } else {
  12. modelNode = objectMapper.createObjectNode();
  13. modelNode.put(MODEL_NAME, model.getName());
  14. }
  15. modelNode.put(MODEL_ID, model.getId());
  16. ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(
  17. new String(repositoryService.getModelEditorSource(model.getId()), "utf-8"));
  18. modelNode.put("model", editorJsonNode);
  19.  
  20. } catch (Exception e) {
  21. LOGGER.error("Error creating model JSON", e);
  22. throw new ActivitiException("Error creating model JSON", e);
  23. }
  24. }
  25. return modelNode;
  26. }
  27. }

  这里看不出什么问题,后来仔细检查,modeler.xml中只配了扫描包,忘记配置<mvc:annotation-driven />。好吧,现在修正了这个问题。至于为什么报了个那么奇怪的错误,暂时没研究。修正之后还是有问题Cannot read property 'namespace' of undefined。这个问题是由于我是直接访问的,看上面的代码也很清楚,首先要创建一个model才会拿着创建的modelId,跳转到这个界面,不然返回数据为空,是无法接下去渲染的。

  小结一下,将modeler整合到自己的项目中步骤如下:

  1.将editor-app文件夹和modeler.html放在项目的webapp文件下,stencilset.json放在resources文件夹下;

  2.maven依赖添加activiti-modeler.jar包

  3.activiti-modeler.jar包采用的是springMVC的形式编写的,按照一般mvc的配置方式,配置一个xml文件扫描其controller层,并启用注解驱动。在web.xml中配置其url路径。

  注意:如果要使用在线流程编辑器,一定要在url modeler.html后带上参数?modelId=xxx,而这个一定要是先创建了的model,不然查出空数据,页面还是空白。所以一般是在创建模型之后,后台重定向到这个地址,顺便带上创建的Id。上述函数返回的json数据给个例子就是:{"name":"test","revision":1,"description":"test","modelId":"1469","model":{"id":"canvas","resourceId":"canvas","stencilset":{"namespace":"http://b3mn.org/stencilset/bpmn2.0#"}}}

  参考咖啡兔写的教程:http://www.kafeitu.me/activiti/2015/12/27/integrate-new-activiti-modeler-and-rest.html?utm_source=tuicool&utm_medium=referral,其还使用了依赖activiti-diagram-rest.jar,说是activiti-modeler模块提供模型先关的操作:创建、保存、转换json与xml格式等,而activiti-diagram-rest模块用来处理流程图有关的功能:流程图布局(layout)、节点高亮等。其实际项目中还导入了diagram-viewer文件夹。具体是否影响功能,我现在还没有了解,等之后如果有需要,还会添加,目前不需要。rest功能目前是不准备添加的。

  至于如何创建一个model,参考咖啡兔的demo,

https://github.com/henryyan/kft-activiti-demo/blob/master/src/main/java/me/kafeitu/demo/activiti/web/workflow/ModelController.java 文件中的create方法就是创建model了,至于前端页面,可以随便写写用于测试就行了。

  

  

activiti搭建(三)整合Modeler的更多相关文章

  1. Intellij Idea系列之Tomcat环境的搭建(三)

    Intellij Idea系列之Tomcat环境的搭建(三) 一. 编写背景 Intellij Idea在刚上手的时候很多人吐槽,"god, 这么难用的IDE有谁用呀?",的确,I ...

  2. windows+mysql集群搭建-三分钟搞定集群

    注:本文来源:  陈晓婵   <  windows+mysql集群搭建-三分钟搞定集群   > 一:mysql集群搭建教程-基础篇 计算机一级考试系统要用集群,目标是把集群搭建起来,保证一 ...

  3. 使用intellij idea搭建spring-springmvc-mybatis整合框架环境

    使用intellij idea搭建spring-springmvc-mybatis整合框架环境   1.打开idea,创建maven项目,File-New-Project 2.选择Maven,勾选Cr ...

  4. Activiti搭建

    Activiti搭建 前期准备: JDK+Eclipse+Tomcat+Maven的安装与配置 参考:http://blog.csdn.net/zhshulin/article/details/307 ...

  5. activiti5.22整合modeler时出错TypeError: Cannot read property 'split' of undefined

    activiti5.22.0整合modeler时,打开的流程页面不显示工具栏和左边的控件栏,产生如下的错误: TypeError: Cannot read property 'split' of un ...

  6. odoo开发环境搭建(三):安装odoo依赖的python包

    odoo开发环境搭建(三):安装odoo依赖的python包 http://www.cnblogs.com/jlzhou/p/5940815.html

  7. 嵌入式框架Zorb Framework搭建三:列表的实现

    我是卓波,我是一名嵌入式工程师,我万万没想到我会在这里跟大家吹牛皮. 嵌入式框架Zorb Framework搭建过程 嵌入式框架Zorb Framework搭建一:嵌入式环境搭建.调试输出和建立时间系 ...

  8. MongoDB:搭建三节点 Replica Set 环境

    今天学习了搭建 MongDB 复制环境,实验环境是在虚拟机上同一系统,并搭建三节点 Replica Set,根据文档上的描述,mongodb 复制配置简单,并且能够自动 failover,这些高级特性 ...

  9. BBS项目分布搭建三(个人站点时间归档补充,实现侧边栏跳转、无线级分类、实现文章详情页展示功能)

    BBS项目分布搭建三(个人站点时间归档补充,) 1. 个人站点时间归档 """ settings.py设置最好更改以下: LANGUAGE_CODE = 'zh-hans ...

随机推荐

  1. 并发容器之ConcurrentSkipListSet

    概要 本章对Java.util.concurrent包中的ConcurrentSkipListSet类进行详细的介绍.内容包括:ConcurrentSkipListSet介绍ConcurrentSki ...

  2. javascript当文本框获得焦点设置边框

    javascript当文本框获得焦点设置边框:本章节介绍一下当文本框获得焦点以后如何设置文本框的边框样式,本来是一个非常简单的问题,但是有可能前台美工人员对javascript并不是太了解,所以还是通 ...

  3. Android 2.3 NFC简介

    Android 2.3加入了NFC(近场通讯)的支持.官网developer.android.com的英文介绍如下:Near Field Communications (NFC)Android 2.3 ...

  4. Good Sentences

    Wine in, truth out One is never too old to learn What is done can not be undone Time tries all thing ...

  5. 理解EnterCriticalSection 临界区

    通俗解释就像上厕所: 门锁了,就等着,等到别人出来了,进去锁上,然后该干什么干什么,干完了,把门打开 门没锁,就进去,锁上,然后该干什么干什么,干完了,把门打开 ------------------- ...

  6. 屏幕分辨率与FPS

    屏幕分辨率 刷新率分为垂直刷新率和水平刷新率,一般提到的刷新率通常指垂直刷新率. 垂直刷新率表示屏幕的图象每秒钟重绘多少次,也就是每秒钟屏幕刷新的次数,以Hz(赫兹)为单位. 刷新率越高越好,图象就越 ...

  7. Js 时间与字符串转示例

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  8. JDK的版本历史

    JDK1.5: 2004年发布----2006年结束 JDK1.6 2006年发布-----2010年结束 一看吓我一条,开始接触JDK都已经是2010年下半年了,可是那是学的就是1.5版本,知道工作 ...

  9. JSON.stringify

    $(document).ready(function (){var things =[{ id:1, color:'yellow'},{ id:2, color:'blue'},{ id:3, col ...

  10. 最小生成树之prim

    prim是设置一个初始结点,寻找其周围最小的边权值,并将该结点作为初始结点,继续寻找现在结点周围的边权值的最小值,但要注意如果这次寻找的某个边权值没有上次的小的话仍然保留上一次的边权值,即lowcas ...