1. 程式人生 > >springboot 繼承 activit 的 modeler 流程設計器

springboot 繼承 activit 的 modeler 流程設計器

以下程式碼為轉載博主文章做備份:

1.編輯器介面

流程編輯器

2.外掛下載

3.編輯器前端部分

僅保留一些靜態資源就行了,將這些檔案放入專案的web目錄下。

需要的檔案

其中的editor-app就是編輯器,modeler.html是編輯器的入口頁面。
diagram-viewer是流程跟蹤外掛,雖然這次用不著,但之後會用到。

還有一個介面元件檔案,在resource下,名稱叫stencilset.json。本身是英文的,可以通過替換它來達到漢化的效果。但現在還是先把它放到專案中去。

介面元件

在editor-app/app-cfg.js中配置一下專案url。這個url是編輯器相關的後臺服務的url。

ACTIVITI.CONFIG = {
    'contextRoot' : '/service',
};

我去掉了專案名。

4.後端部分

先引入兩個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>

其中需要將modeler模組的原始碼放到src中,因為需要在其中做部分修改,主要是url的對映。

其中有3個類,都是Controller:

StencilsetRestResource #獲取編輯器元件及配置項資訊。
ModelEditorJsonRestResource #根據modelId獲取model的節點資訊,編輯器根據返回的json進行繪圖。
ModelSaveRestResource #編輯器製圖之後,將節點資訊以json的形式提交給這個Controller,然後由其進行持久化操作。

需要修改的地方就三個,在每個Controller類上加上@RequestMapping註解,並指定值為"service"(對應前臺app-cfg.js中配置的url)。

···
@RequestMapping("service")
public class StencilsetRestResource {
···
···
@RequestMapping("service")
public class ModelEditorJsonRestResource implements ModelDataJsonConstants {
···
···
@RequestMapping("service")
public class ModelSaveRestResource implements ModelDataJsonConstants {
···

最後別忘了新增包掃描,掃描activiti提供的這些controller。

@SpringBootApplication
@ComponentScan({"org.activiti","com.jerryl"})
public class SpringBootWithActivitiApplication {
···

這樣整合部分就基本結束了,此時編輯器已經可以使用了。

至於介面的漢化,介面上各個元件,各個標籤上的文字都是在resource下的stencilset.json檔案中設定的,可以在網上找一個漢化後的stencilset.json檔案替換掉,就能看到中文介面了。

5.modeler相關方法的封裝

主要需要封裝4個方法:1.新建一個空的模型;2.所有模型列表;3.釋出模型;4.刪除模型;(activiti已提供了儲存和獲取模型節點資訊的方法,就是上面的那3個類)
由於這裡涉及前後端互動,實現方式隨意,主要是activiti的api的呼叫。

參考程式碼:

/**
 * Created by liuruijie on 2017/2/21.
 * 模型管理
 */
@RestController
@RequestMapping("models")
public class ModelerController {

    @Autowired
    ProcessEngine processEngine;
    @Autowired
    ObjectMapper objectMapper;

    /**
     * 新建一個空模型
     * @return
     * @throws UnsupportedEncodingException
     */
    @PostMapping
    public Object newModel() throws UnsupportedEncodingException {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //初始化一個空模型
        Model model = repositoryService.newModel();

        //設定一些預設資訊
        String name = "new-process";
        String description = "";
        int revision = 1;
        String key = "process";

        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
        modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
        modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);

        model.setName(name);
        model.setKey(key);
        model.setMetaInfo(modelNode.toString());

        repositoryService.saveModel(model);
        String id = model.getId();

        //完善ModelEditorSource
        ObjectNode editorNode = objectMapper.createObjectNode();
        editorNode.put("id", "canvas");
        editorNode.put("resourceId", "canvas");
        ObjectNode stencilSetNode = objectMapper.createObjectNode();
        stencilSetNode.put("namespace",
                "http://b3mn.org/stencilset/bpmn2.0#");
        editorNode.put("stencilset", stencilSetNode);
        repositoryService.addModelEditorSource(id,editorNode.toString().getBytes("utf-8"));
        return ToWeb.buildResult().redirectUrl("/modeler.html?modelId="+id);
    }

    /**
     * 獲取所有模型
     * @return
     */
    @GetMapping
    public Object modelList(){
        RepositoryService repositoryService = processEngine.getRepositoryService();
        List<Model> models = repositoryService.createModelQuery().list();
        return ToWeb.buildResult().putData("models", models);
    }

    /**
     * 刪除模型
     * @param id
     * @return
     */
    @DeleteMapping("{id}")
    public Object deleteModel(@PathVariable("id")String id){
        RepositoryService repositoryService = processEngine.getRepositoryService();
        repositoryService.deleteModel(id);
        return ToWeb.buildResult().refresh();
    }

    /**
     * 釋出模型為流程定義
     * @param id
     * @return
     * @throws Exception
     */
    @PostMapping("{id}/deployment")
    public Object deploy(@PathVariable("id")String id) throws Exception {

        //獲取模型
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Model modelData = repositoryService.getModel(id);
        byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());

        if (bytes == null) {
            return ToWeb.buildResult().status(Config.FAIL)
                    .msg("模型資料為空,請先設計流程併成功儲存,再進行釋出。");
        }

        JsonNode modelNode = new ObjectMapper().readTree(bytes);

        BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
        if(model.getProcesses().size()==0){
            return ToWeb.buildResult().status(Config.FAIL)
                    .msg("資料模型不符要求,請至少設計一條主線流程。");
        }
        byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);

        //釋出流程
        String processName = modelData.getName() + ".bpmn20.xml";
        Deployment deployment = repositoryService.createDeployment()
                .name(modelData.getName())
                .addString(processName, new String(bpmnBytes, "UTF-8"))
                .deploy();
        modelData.setDeploymentId(deployment.getId());
        repositoryService.saveModel(modelData);

        return ToWeb.buildResult().refresh();
    }
}

一開始看了博主的原始碼有些地方看不懂

主要類說明:

Cfg_Activiti:此類主要設定了工作流的資料庫,以及設計器的字型樣式。此類還手動註冊了工作流的八大介面,(看了好多部落格說不用手動註冊,但是執行時注入次介面會找不到。所以按博主的方法執行成功的,)後期實現工作流直接可以注入此八大介面,其餘就是建立新的模型。由於博主的前端ajax 自己封裝了的,一開始沒注意

,建立後臺

前臺訪問

一直搞不懂返回一個物件,怎麼會跳轉,後來發現了前臺js,ajax-util.js原來群主把ajax封裝了,自動解析做了請求。由於時間先整理到這裡。