說明
在上一章節中,介紹瞭如何基於bpmn2.0的xml文件發起流程和獲取待辦,其中流程文件和代碼打包在一起,但實際項目中很少會把流程文件和代碼一起打包部署,這樣的話,每次流程更新或者發佈新流程都需要重新部署應用,因此我們制定了以下部署方案:
- 提供流程部署接口,可以通過上傳流程文件對流程進行部署。
- 如果流程文件沒有發生變化,不做新的部署,防止因爲重新部署導致版本號上升。
資源部署
activit部署資源文件需要通過RepositoryService
創建一個deployment
,通過該deployment進行資源的部署,不單單是bpmn流程文件,activiti可以部署任何文件。
上傳資源到activiti
@Service
public class DeploymentService {
@Autowired
private RepositoryService repositoryService;
/**
* deploy resource
*
* @param name resource name
* @param fin resource inputstream
* @return
*/
public String deploy(String name, InputStream fin) {
String deploymentId = repositoryService.createDeployment()
.addInputStream(name, fin)
.name(name)
.key(name)
.deploy()
.getId();
return deploymentId;
}
}
部署的時候指定部署的name
和key
,方便後續對部署進行進一步操作。
聲明restController
@RestController
public class DeploymentController {
@Autowired
private DeploymentService service;
@PostMapping(value = "/deploy")
public String deploy(@RequestParam("file") MultipartFile file) {
try {
return service.deploy(file.getOriginalFilename(), file.getInputStream());
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("upload failed");
}
}
}
這裏以文件名作爲部署的名稱,可以根據實際情況指定名稱。
測試(可以通過postman進行測試,這裏使用curl工具進行上傳測試)
curl -X POST -F '[email protected]' http://localhost:8080/deploy
25001
返回的25001就是部署id。
當執行deploy
操作時,activiti後臺做了以下事
- 在表
ACT_RE_DEPLOYMENT
創建一條記錄 - 將資源存儲至表
ACT_GE_BYTEARRAY
,字段BYTES_
存儲文件內容
流程部署
流程部署和資源部署一樣,但有一點需要注意,部署流程時,資源的名稱必須以bpmn20.xml
或者bpmn
結尾,否則activiti會當作普通資源上傳,你可以在controller上加個判斷避免用戶上錯錯誤文件。
@PostMapping(value = "/deployBpmn")
public String deployBpmn(@RequestParam("file") MultipartFile file) {
try {
String name = file.getOriginalFilename();
if (!name.endsWith(".bpmn20.xm") && !name.endsWith(".bpmn")) {
name = name + ".bpmn";
}
return service.deploy(name, file.getInputStream());
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("upload failed");
}
}
當部署流程後,activit後臺除了執行部署資源的動作外,還額外執行以下動作
- 在表
ACT_RE_PROCDEF
上創建一條記錄,引用deployment_id
。
流程部署優化
以上我們實現了流程的部署,但每次部署都會導致流程版本遞增,我們的方案是如果文件不發生變化則不執行部署操作,保持流程版本好不變,不至於讓版本號升的太快,也節省系統資源。那麼我們需要完成以下兩個邏輯
- 根據key查詢到最新的一次部署
- 獲取最新的一次流程源文件
- 因爲xml是文本文件,我們可以進行文本比對,如果內容一致就認爲版本不變
代碼如下:
/**
* deploy resource
*
* @param name resource name
* @param fin resource inputstream
* @return
*/
public String noChangeNoDeploy(String name, InputStream fin) {
//獲取最新的一次部署
Deployment latestDeployment = repositoryService.createDeploymentQuery()
.deploymentName(name)
.deploymentKey(name)
.latest()
.singleResult();
String sbpmn = ActivitiUtil.text(fin);
if (latestDeployment != null) {
//檢測是否內容發生變化,只重新部署有修改的流程
InputStream input = repositoryService.getResourceAsStream(latestDeployment.getId(), name);
String dbpmn = ActivitiUtil.text(input);
if (sbpmn.length() == dbpmn.length() && sbpmn.equals(dbpmn)) {
return latestDeployment.getId();
}
}
String deploymentId = repositoryService.createDeployment()
.addString(name, sbpmn)
.name(name)
.key(name)
.deploy()
.getId();
return deploymentId;
}
測試:
curl -X POST -F '[email protected]' http://localhost:8080/deployBpmn
27501 curl -X POST -F '[email protected]' http://localhost:8080/deployBpmn
27501
可以看到,如果兩次內容一樣deployid不會改變
其他
除了通過addInputStream
增加資源文件外,RepositoryService
還提供了其他api進行資源的添加。如下
DeploymentBuilder addInputStream(String resourceName, InputStream inputStream);
DeploymentBuilder addClasspathResource(String resource);
DeploymentBuilder addString(String resourceName, String text);
DeploymentBuilder addBytes(String resourceName, byte[] bytes);
DeploymentBuilder addZipInputStream(ZipInputStream zipInputStream);
DeploymentBuilder addBpmnModel(String resourceName, BpmnModel bpmnModel);
本文所有代碼已經上傳至github,倉庫地址爲https://github.com/wls1036/springboot-activiti6-tutorial歡迎star