首先是依賴
<!--flowable工作流依賴-->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.3.0</version>
</dependency>
<!--mysql依賴-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
注意mysql版本問題 否則會報錯
之後
配置數據源
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/flowable-spring-boot?characterEncoding=UTF-8
username: root
password: root
flowable:
activity-font-name: \u5B8B\u4F53(宋體)
label-font-name: \u5B8B\u4F53
annotation-font-name: \u5B8B\u4F53
check-process-definitions: false
這裏上傳文件與流程類型選擇
在後臺首先進行文件類型校對
boolean temp = Objects.requireNonNull(file.getOriginalFilename()).endsWith(FlowEngineConstant.SUFFIX);
String SUFFIX = ".bpmn20.xml";
即校對文件後綴名
之後就是執行具體的方法部署
public R deployUpload(@RequestParam List<MultipartFile> files, @RequestParam String category) {
return R.status(flowService.deployUpload(files, category));
}
@Override
public boolean deployUpload(List<MultipartFile> files, String category) {
files.forEach(file -> {
try {
String fileName = file.getOriginalFilename();
InputStream fileInputStream = file.getInputStream();
//repositoryService.createDeployment(); //流程部署對象,返會deploymentBuilder
//加載流程文件,從類路徑加載
// // deploymentBuilder.addInputStream
//2.使用InputStream加載 (替換自己的文件路徑)
//執行部署,直到調用deploy()方法纔是真正的部署到引擎中了
//同時會在act_ge_bytearray ,act_re_deployment ,act_re_procdef這3個表中插入相關信息
//與以前的教程不一樣的是,別的教程中會經常將流程圖片和流程bpmn文件一起部署,但我認爲有點多餘了,因爲在部署bpmn的時候會自動生成流程圖片
Deployment deployment = repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy();
//定義流程
deploy(deployment, category);
} catch (IOException e) {
e.printStackTrace();
}
});
return true;
}
然後給定義好的流程 配好類型
private boolean deploy(Deployment deployment, String category) {
log.debug("流程部署--------deploy: " + deployment + " 分類---------->" + category);
// 使用repositoryService查詢多個流程實例
//createProcessDefinitionQuery()//查詢過程定義。返回processDefinitionQuery
// processDefinitionQuery.deploymentId("1");//使用部署對象ID查詢
// List<ProcessDefinition> list = processDefinitionQuery.list();//多個結果集
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
StringBuilder logBuilder = new StringBuilder(500);
List<Object> logArgs = new ArrayList<>();
// 設置流程分類
for (ProcessDefinition processDefinition : list) {
if (StringUtil.isNotBlank(category)) {
repositoryService.setProcessDefinitionCategory(processDefinition.getId(), category);
}
logBuilder.append("部署成功,流程ID={} \n");
logArgs.add(processDefinition.getId());
}
if (list.size() == 0) {
throw new ServiceException("部署失敗,未找到流程");
} else {
log.info(logBuilder.toString(), logArgs.toArray());
return true;
}
}
上傳部署工作完成
然後就可以看到
public R<IPage<FlowProcess>> list(@ApiParam("流程類型") String category, Query query) {
IPage<FlowProcess> pages = flowService.selectProcessPage(Condition.getPage(query), category);
return R.data(pages);
}
private static final String IMAGE_NAME = "image";
private static final String XML_NAME = "xml";
@Override
public IPage<FlowProcess> selectProcessPage(IPage<FlowProcess> page, String category) {
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().latestVersion().orderByProcessDefinitionKey().asc();
if (StringUtils.isNotEmpty(category)) {
//加入查詢條件
processDefinitionQuery.processDefinitionCategory(category);
}
//查詢流程定義
List<ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage(Func.toInt((page.getCurrent() - 1) * page.getSize()), Func.toInt(page.getSize()));
List<FlowProcess> flowProcessList = new ArrayList<>();
//將flowable內部的流程放到轉爲自己的進行使用
processDefinitionList.forEach(processDefinition -> {
String deploymentId = processDefinition.getDeploymentId();
//ProcessDefinition processDefinition = processDefinitionQuery.singleResult();//唯一結果集
Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
FlowProcess flowProcess = new FlowProcess((ProcessDefinitionEntityImpl) processDefinition);
flowProcess.setDeploymentTime(deployment.getDeploymentTime());
flowProcessList.add(flowProcess);
});
page.setTotal(processDefinitionQuery.count());
page.setRecords(flowProcessList);
return page;
}
然後流程圖顯示:
private static final String IMAGE_NAME = "image";
private static final String XML_NAME = "xml";
private static final Integer INT_1024 = 1024;
@GetMapping("resource-view")
public void resourceView(@RequestParam String processDefinitionId, String processInstanceId, @RequestParam(defaultValue = IMAGE_NAME) String resourceType, HttpServletResponse response) throws Exception {
if (StringUtil.isAllBlank(processDefinitionId, processInstanceId)) {
return;
}
if (StringUtil.isBlank(processDefinitionId)) {
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
processDefinitionId = processInstance.getProcessDefinitionId();
}
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
String resourceName = "";
if (resourceType.equals(IMAGE_NAME)) {
resourceName = processDefinition.getDiagramResourceName();
} else if (resourceType.equals(XML_NAME)) {
resourceName = processDefinition.getResourceName();
}
////通過一個字節流提供對部署資源的訪問。InputStream getResourceAsStream(String deploymentId, String resourceName);
InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
byte[] b = new byte[1024];
int len;
while ((len = resourceAsStream.read(b, 0, INT_1024)) != -1) {
response.getOutputStream().write(b, 0, len);
}
}
變更流程狀態爲
public R changeState(@RequestParam String state, @RequestParam String processId) {
String msg = flowService.changeState(state, processId);
return R.success(msg);
}
@Override
public String changeState(String state, String processId) {
if (state.equals(FlowEngineConstant.ACTIVE)) {
repositoryService.activateProcessDefinitionById(processId, true, null);
return StringUtil.format("激活ID爲 [{}] 的流程成功", processId);
} else if (state.equals(FlowEngineConstant.SUSPEND)) {
repositoryService.suspendProcessDefinitionById(processId, true, null);
return StringUtil.format("掛起ID爲 [{}] 的流程成功", processId);
} else {
return "暫無流程變更";
}
}
刪除流程
public R deleteDeployment(String deploymentIds) {
return R.status(flowService.deleteDeployment(deploymentIds));
}
@Override
public boolean deleteDeployment(String deploymentIds) {
Func.toStrList(deploymentIds).forEach(
deploymentId -> repositoryService.deleteDeployment(deploymentId, true));
return true;
}
至此完成整個工作流的部署工作
RepositoryService服務類
一共47個接口
1.創建部署
//開始創建一個新的部署。
DeploymentBuilder createDeployment();
2.刪除部署(3個)
//刪除給定的部署。
void deleteDeployment(String deploymentId);
//將給定的部署和級聯刪除刪除到流程實例、歷史流程實例和作業。
void deleteDeploymentCascade(String deploymentId);
//同上
void deleteDeployment(String deploymentId, boolean cascade);
3.設置部署
//設置部署的類別。
可以按類別查詢部署:參見{@link DeploymentQuery#deploymentCategory(String)}。
void setDeploymentCategory(String deploymentId, String category);
4.獲取部署
//檢索給定部署的部署資源列表,按字母順序排列。
List<String> getDeploymentResourceNames(String deploymentId);
//通過一個字節流提供對部署資源的訪問。
InputStream getResourceAsStream(String deploymentId, String resourceName);
//實驗功能
更改部署的租戶標識符,以匹配給定的租戶標識符。
這一變化將波及任何相關實體:
void changeDeploymentTenantId(String deploymentId, String newTenantId);
5.創建
//查詢過程定義。
ProcessDefinitionQuery createProcessDefinitionQuery();
//爲流程定義返回一個新{@link org.activiti.engine.query.NativeQuery}。
NativeProcessDefinitionQuery createNativeProcessDefinitionQuery();
//查詢部署。
DeploymentQuery createDeploymentQuery();
//返回一個新的部署{@link org.activiti.engine.query.NativeQuery}
NativeDeploymentQuery createNativeDeploymentQuery();
6.暫停流程
//用給定的id暫停流程定義。
void suspendProcessDefinitionById(String processDefinitionId);
//同上
void suspendProcessDefinitionById(String processDefinitionId, boolean suspendProcessInstances, Date suspensionDate);
//用給定的鍵(= id in the bpmn20.xml file)掛起所有的進程定義。
xml文件)。
void suspendProcessDefinitionByKey(String processDefinitionKey);
//同上
void suspendProcessDefinitionByKey(String processDefinitionKey, boolean suspendProcessInstances, Date suspensionDate);
//類似{@link #suspendProcessDefinitionByKey(String)}但只適用於給定的租戶標識符。
void suspendProcessDefinitionByKey(String processDefinitionKey, String tenantId);
//類似{@link #suspendProcessDefinitionByKey(String, boolean, Date)}但只適用於給定的租戶標識符。
void suspendProcessDefinitionByKey(String processDefinitionKey, boolean suspendProcessInstances, Date suspensionDate, String tenantId);
7.激活流程
//用給定的id激活流程定義。
void activateProcessDefinitionById(String processDefinitionId);
//同上
void activateProcessDefinitionById(String processDefinitionId, boolean activateProcessInstances, Date activationDate);
//用給定的key(=id in the bpmn20.xml file)激活流程定義。
void activateProcessDefinitionByKey(String processDefinitionKey);
//同上
void activateProcessDefinitionByKey(String processDefinitionKey, boolean activateProcessInstances, Date activationDate);
//類似於{@link #activateProcessDefinitionByKey(String)}但只適用於給定的租戶標識符。
void activateProcessDefinitionByKey(String processDefinitionKey, String tenantId);
//類似於{@link #activateProcessDefinitionByKey(String, boolean, Date)}但只適用於給定的租戶標識符。
void activateProcessDefinitionByKey(String processDefinitionKey, boolean activateProcessInstances, Date activationDate, String tenantId);
8.設置流程定義類別
//設置流程定義的類別。
流程定義可以查詢類別:看到{ @link ProcessDefinitionQuery # processDefinitionCategory(String)}。
void setProcessDefinitionCategory(String processDefinitionId, String category);
9.訪問已部署流程
//提供對已部署過程模型的訪問,例如,一個BPMN 2.0 XML文件,通過一個字節流。
InputStream getProcessModel(String processDefinitionId);
//提供對已部署流程圖的訪問,例如PNG圖像,通過一個字節流。
InputStream getProcessDiagram(String processDefinitionId);
//返回{@link ProcessDefinition},包括所有BPMN信息,如附加屬性(如文檔)。
ProcessDefinition getProcessDefinition(String processDefinitionId);
//使用提供的流程定義id返回與流程定義對應的{@link BpmnModel}。
BpmnModel getBpmnModel(String processDefinitionId);
10.檢測流程狀態
//檢查流程定義是否被掛起。
boolean isProcessDefinitionSuspended(String processDefinitionId);
//在流程關係圖中提供元素的位置和維度,如{@link RepositoryService#getProcessDiagram(String)}所提供的。
DiagramLayout getProcessDiagramLayout(String processDefinitionId);
11.模型的增刪改查
//創建一個新的model,他的模型是暫時的,必須使用{@link #saveModel(模型)}來保存。
Model newModel();
//保存模型。
如果模型已經存在,那麼模型就會被更新,否則就會創建一個新的模型。
void saveModel(Model model);
//刪除model
void deleteModel(String modelId);
//爲模型保存模型編輯器源。
void addModelEditorSource(String modelId, byte[] bytes);
//同上
void addModelEditorSourceExtra(String modelId, byte[] bytes);
//創建查詢模型
ModelQuery createModelQuery();
//爲流程定義返回一個新{@link org.activiti.engine.query.NativeQuery}
NativeModelQuery createNativeModelQuery();
//返回{@link Model}
Model getModel(String modelId);
//以字節數組的形式返回模型編輯器源。
byte[] getModelEditorSource(String modelId);
//同上
byte[] getModelEditorSourceExtra(String modelId);
12.授權用戶
//授權候選用戶進行流程定義。
void addCandidateStarterUser(String processDefinitionId, String userId);
//授權候選用戶組進行流程定義。
void addCandidateStarterGroup(String processDefinitionId, String groupId);
//刪除候選用戶對流程定義的授權。
void deleteCandidateStarterUser(String processDefinitionId, String userId);
//刪除候選用戶組對流程定義的授權。
void deleteCandidateStarterGroup(String processDefinitionId, String groupId);
//檢索與給定進程定義關聯的{@link IdentityLink}。
這樣的{@link IdentityLink}通知了一個特定的標識(如。
組或用戶)被授權用於特定的流程定義。
List<IdentityLink> getIdentityLinksForProcessDefinition(String processDefinitionId);
//根據對Activiti引擎執行流程定義的規則,驗證給定的流程定義。
List<ValidationError> validateProcess(BpmnModel bpmnModel);
還有一些其他的可以自己去查看