<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                > 前面我們介紹了流程模型的創建、以及用流程模型部署流程定義。本節我們主要介紹,流程定義文件—流程定義—流程模型的相互轉化 [TOC] ***** ## 1、回顧 ### 1.1 、生成流程模型 此處貼出生成流程模型的代碼,流程模型是啥?說白了就是創建一個流程模型,然后我們可以在上面畫流程圖。 ~~~ /** * 創建模型 */ @Test public void create() { String name = "請假流程"; String key = "leave"; String description = "這是一個簡單的請假流程"; try { ObjectMapper objectMapper = new ObjectMapper(); 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); ObjectNode modelObjectNode = objectMapper.createObjectNode(); modelObjectNode.put(MODEL_NAME, name); modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1); description = StringUtils.defaultString(description); modelObjectNode.put(MODEL_DESCRIPTION, description); Model newModel = repositoryService.newModel(); newModel.setMetaInfo(modelObjectNode.toString()); newModel.setName(name); newModel.setKey(StringUtils.defaultString(key)); repositoryService.saveModel(newModel); repositoryService.addModelEditorSource(newModel.getId(), editorNode.toString().getBytes("utf-8")); System.out.println("生成的moduleId:"+newModel.getId()); } catch (Exception e) { } } ~~~ ### 1.2 、部署流程定義 這個在前面的章節已經介紹過了,把畫好的流程圖部署好才能發起流程。 ~~~ /** * 部署流程定義 */ @Test public void deployTest(){ Deployment deployment = repositoryService.createDeployment() .addClasspathResource("leave.bpmn") .deploy(); assertNotNull(deployment); } ~~~ ### 1.3 、 引出問題 **第一個問題**:步驟 1.2 中,部署流程定義是直接使用`leave.bpmn`文件部署的。但是我們使用Activiti Modeler設計流程圖后,流程模型數據是直接保存在數據庫表中的(act\_re\_model)。并不是直接生成一個`.bpmn`文件。這時如何部署流程定義呢? * 方式一:使用Activiti Modeler 設計器保存在act\_re\_model表中的模型記錄,導出一個`.bpmn`文件后再部署(不方便) * 方式二:直接使用 act\_re\_model 表中的模型記錄來部署流程定義。(正確用法) **第二個問題**:就是如果我們現在只有一個別人提供的`.bpmn`文件,如何才能將它保存到`act_re_model`表中呢? 思路如下: ![](https://img.kancloud.cn/d1/dc/d1dc57b6883451791051b412d11a5881_977x455.png) ## 2、流程定義文件—流程定義—流程模型 相互轉化 ### 2.1 、 bpmn文件轉流程定義(act\_re\_procdef) > 上面的1.2 中,我們是直接將文件放在了`src/main/resources`目錄下。下面我們改造一下。改為上傳附件部署流程定義。 這里改動較大、把常用工具類類單獨放在了workflow-common這個module中。貼出關鍵代碼: 新建 ProcessDefinitionController.java ~~~ package com.sxdx.workflow.activiti.rest.controller; import com.sxdx.common.config.GlobalConfig; import com.sxdx.common.constant.CodeEnum; import com.sxdx.common.constant.Constants; import com.sxdx.common.util.CommonResponse; import com.sxdx.common.util.StringUtils; import com.sxdx.common.util.file.FileUploadUtils; import com.sxdx.workflow.activiti.rest.service.ProcessDefinitionService; import org.activiti.engine.RepositoryService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @Controller @RequestMapping("/definition") public class ProcessDefinitionController { private static final Logger log = LoggerFactory.getLogger(ProcessDefinitionController.class); private String prefix = "definition"; @Autowired private ProcessDefinitionService processDefinitionService; @Autowired private RepositoryService repositoryService; /** * 部署流程定義 */ @PostMapping("/upload") @ResponseBody public CommonResponse upload(@RequestParam("processDefinition") MultipartFile file) { try { if (!file.isEmpty()) { String extensionName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.') + 1); if (!"bpmn".equalsIgnoreCase(extensionName) && !"zip".equalsIgnoreCase(extensionName) && !"bar".equalsIgnoreCase(extensionName)) { return new CommonResponse().code(CodeEnum.FAILURE.getCode()).message("流程定義文件僅支持 bpmn, zip 和 bar 格式!"); } // p.s. 此時 FileUploadUtils.upload() 返回字符串 fileName 前綴為 Constants.RESOURCE_PREFIX,需剔除 // 詳見: FileUploadUtils.getPathFileName(...) String fileName = FileUploadUtils.upload(GlobalConfig.getProfile() + "/processDefiniton", file); if (StringUtils.isNotBlank(fileName)) { String realFilePath = GlobalConfig.getProfile() + fileName.substring(Constants.RESOURCE_PREFIX.length()); processDefinitionService.deployProcessDefinition(realFilePath); return new CommonResponse().code(CodeEnum.SUCCESS.getCode()).message("部署成功"); } } return new CommonResponse().code(CodeEnum.FAILURE.getCode()).message("不允許上傳空文件!"); } catch (Exception e) { log.error("上傳流程定義文件失敗!", e); return new CommonResponse().code(CodeEnum.FAILURE.getCode().toString()).message(e.getMessage()); } } } ~~~ 我們使用postman做測試: 支持單個bpmn文件上傳,也支持多個文件壓縮成zip包、或者bar包 ![](https://img.kancloud.cn/7b/0c/7b0cfda9325649f6826fc0c684f16542_1538x602.png) 然后我們查看`act_re_deployment`和`act_re_procdef`表,可以看到已經生成了對應的流程定義記錄(我執行了2次,所以2條記錄) ![](https://img.kancloud.cn/db/a7/dba72969ff583afeb9e32e46e799a366_882x180.png) ![](https://img.kancloud.cn/da/79/da79c0c1c301a1dda0850d6f9625d14b_1566x125.png) 然后我們就可以根據流程定義來發起流程了,本節我們主要介紹內容不是這個,我們先來介紹流程定義如何轉化流程模型。 ### 2.2、流程定義(act\_re\_procdef)轉流程模型(act\_re\_model) 執行代碼如下: ~~~ /** * 轉換流程定義為模型 * @param processDefinitionId 流程定義id * @return * @throws UnsupportedEncodingException * @throws XMLStreamException */ @PostMapping(value = "/convertToModel") @ResponseBody public CommonResponse convertToModel(@Param("processDefinitionId") String processDefinitionId) throws UnsupportedEncodingException, XMLStreamException { org.activiti.engine.repository.ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .processDefinitionId(processDefinitionId).singleResult(); InputStream bpmnStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName()); XMLInputFactory xif = XMLInputFactory.newInstance(); InputStreamReader in = new InputStreamReader(bpmnStream, "UTF-8"); XMLStreamReader xtr = xif.createXMLStreamReader(in); BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr); BpmnJsonConverter converter = new BpmnJsonConverter(); ObjectNode modelNode = converter.convertToJson(bpmnModel); Model modelData = repositoryService.newModel(); modelData.setKey(processDefinition.getKey()); modelData.setName(processDefinition.getResourceName()); modelData.setCategory(processDefinition.getDeploymentId()); ObjectNode modelObjectNode = new ObjectMapper().createObjectNode(); modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processDefinition.getName()); modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1); modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription()); modelData.setMetaInfo(modelObjectNode.toString()); repositoryService.saveModel(modelData); repositoryService.addModelEditorSource(modelData.getId(), modelNode.toString().getBytes("utf-8")); return new CommonResponse().code(CodeEnum.SUCCESS.getCode()).message("轉換成功"); } ~~~ postman測試結果(參數是流程定義id,即`act_re_procdef`表的主鍵id) ![](https://img.kancloud.cn/19/93/19939010b410805a21fe6661656cf46d_1523x590.png) 轉化成功后,我們查看`act_re_model`表,可以看到已經生成了對應的流程模型。 ![](https://img.kancloud.cn/ce/f4/cef42e51333c905b0b57b07c9d8ecf0c_1570x146.png) ### 2.3、流程模型(act\_re\_model)轉流程定義(act\_re\_procdef) 新建ModelerController.java: ~~~ ** * 根據Model部署流程,參數為act_re_model表的ID_字段 */ @RequestMapping(value = "/modeler/deploy/{modelId}") @ResponseBody public AjaxResult deploy(@PathVariable("modelId") String modelId, RedirectAttributes redirectAttributes) { try { Model modelData = repositoryService.getModel(modelId); ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId())); byte[] bpmnBytes = null; BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode); 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(); LOGGER.info("部署成功,部署ID=" + deployment.getId()); return success("部署成功"); } catch (Exception e) { LOGGER.error("根據模型部署流程失敗:modelId={}", modelId, e); } return error("部署失敗"); } /** * 導出model的xml文件 */ @RequestMapping(value = "/modeler/export/{modelId}") public void export(@PathVariable("modelId") String modelId, HttpServletResponse response) { try { Model modelData = repositoryService.getModel(modelId); BpmnJsonConverter jsonConverter = new BpmnJsonConverter(); JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId())); BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode); // 流程非空判斷 if (!CollectionUtils.isEmpty(bpmnModel.getProcesses())) { BpmnXMLConverter xmlConverter = new BpmnXMLConverter(); byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel); ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes); String filename = bpmnModel.getMainProcess().getId() + ".bpmn"; response.setHeader("Content-Disposition", "attachment; filename=" + filename); IOUtils.copy(in, response.getOutputStream()); response.flushBuffer(); } else { try { response.sendRedirect("/modeler/modelList"); } catch (IOException ex) { ex.printStackTrace(); } } } catch (Exception e) { LOGGER.error("導出model的xml文件失敗:modelId={}", modelId, e); try { response.sendRedirect("/modeler/modelList"); } catch (IOException ex) { ex.printStackTrace(); } } } ~~~ ![](https://img.kancloud.cn/25/16/25160b405c032b3203d7f3d989695099_1520x582.png) ![](https://img.kancloud.cn/59/a6/59a65fc7c76b2dc8f09dab0ef039ef8a_1482x102.png) 我們查看對應的數據庫表: ![](https://img.kancloud.cn/c0/ca/c0ca6c45739e530f1977d38e7bee5d39_1171x268.png) ![](https://img.kancloud.cn/22/01/220122f2c8bd4fb32ffc5b683bf5eee1_1663x299.png) 可以看到生成了對應的流程定義,因為我們使用的是同一個KEY的流程,所以生成的記錄的VERSION\_字段(版本)自動遞增變為了3。有一點需要說明。當我們直接使用流程定義KEY(這里是leaveCounterSign)發起流程時,系統會默認選擇吧版本更高的流程定義。 ### 2.4、將流程模型導出為bpmn文件 ~~~ /** * 將流程模型導出為 bpmn文件 */ @RequestMapping(value = "/modeler/export/{modelId}") public void export(@PathVariable("modelId") String modelId, HttpServletResponse response) { try { Model modelData = repositoryService.getModel(modelId); BpmnJsonConverter jsonConverter = new BpmnJsonConverter(); JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId())); BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode); // 流程非空判斷 if (!CollectionUtils.isEmpty(bpmnModel.getProcesses())) { BpmnXMLConverter xmlConverter = new BpmnXMLConverter(); byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel); ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes); String filename = bpmnModel.getMainProcess().getId() + ".bpmn"; response.setHeader("Content-Disposition", "attachment; filename=" + filename); IOUtils.copy(in, response.getOutputStream()); response.flushBuffer(); } else { logger.error("導出model的xml文件失敗:modelId={}", modelId); } } catch (Exception e) { logger.error("導出model的xml文件失敗:modelId={}", modelId, e); } } ~~~ 測試結果: ![](https://img.kancloud.cn/2e/86/2e8611ab844fc62a1a395972b4b36984_1529x876.png) 如果直接使用瀏覽器訪問,則會下載bpmn文件 ![](https://img.kancloud.cn/74/79/7479b489c6338de5fdf1c6e1db135d34_1397x648.png) ### 2.5、創建流程模型 這個我們在第3節已經介紹過,不做其他介紹。直接貼代碼: ~~~ /** * 創建模型 */ @RequestMapping(value = "/modeler/create") @ResponseBody public CommonResponse create(@RequestParam(value = "name",required=true) String name, @RequestParam(value = "key",required=true) String key, @RequestParam(value = "description",required=true) String description) { /* String name = "請假流程"; String key = "qingjia"; String description = "這是一個簡單的請假流程";*/ try { ObjectMapper objectMapper = new ObjectMapper(); 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); ObjectNode modelObjectNode = objectMapper.createObjectNode(); modelObjectNode.put(MODEL_NAME, name); modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1); description = StringUtils.defaultString(description); modelObjectNode.put(MODEL_DESCRIPTION, description); Model newModel = repositoryService.newModel(); newModel.setMetaInfo(modelObjectNode.toString()); newModel.setName(name); newModel.setKey(StringUtils.defaultString(key)); repositoryService.saveModel(newModel); repositoryService.addModelEditorSource(newModel.getId(), editorNode.toString().getBytes("utf-8")); System.out.println("生成的moduleId:"+newModel.getId()); return new CommonResponse().code(CodeEnum.SUCCESS.getCode()).message("部署成功").data(newModel); } catch (Exception e) { logger.error("創建模型失敗"); } return new CommonResponse().code(CodeEnum.SUCCESS.getCode()).message("部署成功"); } ~~~ ![](https://img.kancloud.cn/a5/bd/a5bd4220c1b3cccbbf42eafbb090b208_1531x879.png) ### 2.6 、查看流程模型 訪問[http://localhost:8080/modeler/modeler.html?modelId=1](http://localhost:8080/modeler/modeler.html?modelId=1) 就可以愉快的在上面設計流程圖了。 ![](https://img.kancloud.cn/c1/eb/c1eb72b8a7ea472cc1997d745a170b39_2544x1246.png) 流程定義文件—流程定義—流程模型 之間的相互轉化,就介紹到這里。 ### 2.7、刪除已部署的流程定義 ~~~ /** * 刪除已部署的流程定義 * @param deploymentId 流程部署ID */ @GetMapping(value = "/process/delete/{deploymentId}") @ApiOperation(value = "刪除已部署的流程定義",notes = "刪除已部署的流程定義") public CommonResponse delete(@PathVariable("deploymentId") @ApiParam("流程定義ID (act_re_deployment表id)") String deploymentId) { List<ProcessInstance> instanceList = runtimeService.createProcessInstanceQuery() .deploymentId(deploymentId) .list(); if (!CollectionUtils.isEmpty(instanceList)) { // 存在流程實例的流程定義 throw new CommonException("刪除失敗,存在運行中的流程實例"); } repositoryService.deleteDeployment(deploymentId, true); // true 表示級聯刪除引用,比如 act_ru_execution 數據 return new CommonResponse().code(CodeEnum.SUCCESS.getCode()).message("刪除流程實例成功"); } ~~~ ![](https://img.kancloud.cn/00/76/00762bf3cffed8e9a70f2f4ae7fa0e86_1775x1155.png) ### 2.8、刪除流程模型 ``` @GetMapping(value = "/modeler/delete/{modelId}") @ApiOperation(value = "刪除流程模型",notes = "刪除流程模型") public CommonResponse remove(@PathVariable("modelId") @ApiParam("流程模型Id") String modelId) { repositoryService.deleteModel(modelId); return new CommonResponse().code(CodeEnum.SUCCESS.getCode()).message("刪除流程模型成功"); } ``` ![](https://img.kancloud.cn/34/d7/34d79f18034450c29405f9a25c41e378_1823x1156.png) ## 3、內容補充 ### 3.1 獲取流程模型列表 此處添加一個獲取流程模型列表的接口,其中用到了**自定義分頁插件**。自定義分頁插件在后面的**歷史數據模塊、補充獲取流程定義列表接口**中會有介紹。 ``` @GetMapping(value = "/modelList") @ApiOperation(value = "獲取流程模型列表",notes = "獲取流程模型列表") public CommonResponse getModelerList(@RequestParam(value = "pageNum", required = false,defaultValue = "1") @ApiParam(value = "頁碼" ,required = false)int pageNum, @RequestParam(value = "pageSize", required = false,defaultValue = "10") @ApiParam(value = "條數" ,required = false)int pageSize){ ModelQuery modelQuery = repositoryService.createModelQuery(); Page page = new Page(pageNum,pageSize); List<Model> list = modelQuery.orderByCreateTime().desc() .listPage(page.getFirstResult(),page.getMaxResults()); int total = (int) modelQuery.count(); page.setTotal(total); page.setList(list); return new CommonResponse().code(CodeEnum.SUCCESS.getCode()).message("獲取流程模型列表成功").data(page); } ``` ![](https://img.kancloud.cn/f1/ab/f1ab9f97e18c2d3878aa1ae47a9a626b_1282x933.png)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看