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封裝了,自動解析做了請求。由於時間先整理到這裡。