activiti搭建(三)整合Modeler


  轉載請注明源地址: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中的一個方法中:

    /* Helper method to fetch model from server (always needed) */
            function fetchModel(modelId) {

                var modelUrl = KISBPM.URL.getModel(modelId);

                $http({method: 'GET', url: modelUrl}).
                    success(function (data, status, headers, config) {
                        $rootScope.editor = new ORYX.Editor(data);
                        $rootScope.modelData = angular.fromJson(data);
                        $rootScope.editorFactory.resolve();
                    }).
                    error(function (data, status, headers, config) {
                      console.log('Error loading model with id ' + modelId + ' ' + data);
                    });
            }    

  斷點截圖:

   第二個問題實際上Activiti Modeler的后台服務官方是給出了的,都放在了activiti-modeler.jar包中,其采用的是spring-mvc的形式。所以在pom.xml中添加相關依賴:

		<dependency>
			<groupId>org.activiti</groupId>
			<artifactId>activiti-modeler</artifactId>
			<version>5.21.0</version>
		</dependency>

  查看activiti-modeler源碼,發現里面十分簡單,一共只有三個類,對應着三個URL,分別是:

  /editor/stencilset 用來加載並返回stencilset.json文件的內容

  /model/{modelId}/json 這個就是訪問的那個url了,通過部署的modelId模型編輯源

  /model/{modelId}/save 這個是用來保存編輯的模型

  知道這些之后,我們再在resources文件夾下創建一個spring-mvc-modeler.xml用於提供對Activiti Modeler后台URL的支持。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd 
	http://www.springframework.org/schema/context 
	http://www.springframework.org/schema/context/spring-context.xsd 
	http://www.springframework.org/schema/mvc
	http://www.springframework.org/schema/mvc/spring-mvc.xsd">
	
	<!-- mvc中只掃controller層,而modeler模塊也只有controller層-->
	<context:component-scan base-package="org.activiti.rest.editor">
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
	</context:component-scan>
	
	<!-- modeler需要自動注入ObjectMapper -->
	<bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper"/>
	
	<mvc:annotation-driven />
</beans>

  在web.xml中配置路徑分發:

	<servlet>
		<servlet-name>ModelerServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring-mvc-modeler.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>ModelerServlet</servlet-name>
		<!-- url要與app-cfg.js中配置的一致 -->
		<url-pattern>/service/*</url-pattern>
	</servlet-mapping>

  配置完成后,啟動項目不會報錯,但是訪問依舊是404not found,/項目名/service/model//json 查看后台,方法沒有被執行,這個可能是少了中間的參數,url沒有匹配。先看前台url配置。url是配置在了configuration文件夾下的url-config中。繼續查找源碼,看是哪里調用了這個方法,在app.js中發現:

            /**
             * Initialize the Oryx Editor when the content has been loaded
             */
            $rootScope.$on('$includeContentLoaded', function (event) {
	            if (!$rootScope.editorInitialized) {

	            	ORYX._loadPlugins();
	
	                var modelId = EDITOR.UTIL.getParameterByName('modelId');
	                fetchModel(modelId);
                        ...
            }        

  EDITOR.UTIL.getParameterByName('modelId'),查找源碼在editor-utils.js中找到這塊代碼:

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

   這樣就很明顯了,在訪問這個界面的時候要帶上查詢參數,必須訪問地址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/這段。查看源碼,斷點調試:

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

  這里看不出什么問題,后來仔細檢查,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了,至於前端頁面,可以隨便寫寫用於測試就行了。

  

 

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM