IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 使用Camunda流程引擎开发,如何读取流程图中配制的参数及参数值? -> 正文阅读

[开发测试]使用Camunda流程引擎开发,如何读取流程图中配制的参数及参数值?

在使用开源?Camunda 流程引擎框架做二次开发,有时候会在固定节点添加固定的参数及参数值,流程在流转到此节点时,我们如何运用Camunda从中取出配制的参数呢?

?

下面首先介绍?Camunda 支持配制哪些参数:
  1. String
  2. Map
  3. List
  4. Script
  5. String or Expression
Camunda中,除开1类型之外,其它四种都是以对象的方式保存在流程中(解析出来保存在?ACT_GE_BYTEARRAY 表中)。 配制String类型的是在 Extensions ;其它4种是在 ?Input/Output?

?

上面介绍了使用?Camunda Modeler 流程图工具配制参数,下面来看下流程图是如何取到这些值的。

?

读取这些值的方法还是很简单,只有一句代码:
Map<String, Object> map = runtimeService.getVariables(task.getExecutionId());
读取配制的值很简单,那有没有想过这些值是怎么取到的呢?
大胆猜想一下,就是在部署流程解析XML文件的时候,这些值就解析出来了,然后在保存在缓存中。
有了猜想,下面再来验证我们的猜想。
protected DeploymentWithDefinitions doExecute(final CommandContext commandContext) {
??DeploymentManager deploymentManager = commandContext.getDeploymentManager();


??// load deployment handler
??ProcessEngine processEngine = commandContext.getProcessEngineConfiguration().getProcessEngine();
??deploymentHandler = commandContext.getProcessEngineConfiguration()
??????.getDeploymentHandlerFactory()
??????.buildDeploymentHandler(processEngine);


??Set<String> deploymentIds = getAllDeploymentIds(deploymentBuilder);
??if (!deploymentIds.isEmpty()) {
????String[] deploymentIdArray = deploymentIds.toArray(new String[deploymentIds.size()]);
????List<DeploymentEntity> deployments = deploymentManager.findDeploymentsByIds(deploymentIdArray);
????ensureDeploymentsWithIdsExists(deploymentIds, deployments);
??}


??checkCreateAndReadDeployments(commandContext, deploymentIds);


??// set deployment name if it should retrieved from an existing deployment
??String nameFromDeployment = deploymentBuilder.getNameFromDeployment();
??setDeploymentName(nameFromDeployment, deploymentBuilder, commandContext);


??// get resources to re-deploy
??List<ResourceEntity> resources = getResources(deploymentBuilder, commandContext);
??// .. and add them the builder
??addResources(resources, deploymentBuilder);


??Collection<String> resourceNames = deploymentBuilder.getResourceNames();
??if (resourceNames == null || resourceNames.isEmpty()) {
????throw new NotValidException("No deployment resources contained to deploy.");
??}


??// perform deployment ??
??DeploymentWithDefinitions deployment =?commandContext.runWithoutAuthorization(() -> {
????acquireExclusiveLock(commandContext);
????DeploymentEntity deploymentToRegister = initDeployment();
????Map<String, ResourceEntity> resourcesToDeploy =
????????resolveResourcesToDeploy(commandContext, deploymentToRegister);
????Map<String, ResourceEntity> resourcesToIgnore = new HashMap<>(deploymentToRegister.getResources());
????resourcesToIgnore.keySet().removeAll(resourcesToDeploy.keySet());


????// save initial deployment resources before they are replaced with only the deployed ones
????CandidateDeployment candidateDeployment =
????????CandidateDeploymentImpl.fromDeploymentEntity(deploymentToRegister);
????if (!resourcesToDeploy.isEmpty()) {
??????LOG.debugCreatingNewDeployment();
??????deploymentToRegister.setResources(resourcesToDeploy);
??????deploy(commandContext, deploymentToRegister);
????} else {
??????// if there are no resources to be deployed, find an existing deployment
??????String duplicateDeploymentId =
??????????deploymentHandler.determineDuplicateDeployment(candidateDeployment);
??????deploymentToRegister =
??????????commandContext.getDeploymentManager().findDeploymentById(duplicateDeploymentId);
????}


????scheduleProcessDefinitionActivation(commandContext, deploymentToRegister);


????if(deploymentBuilder instanceof ProcessApplicationDeploymentBuilder) {
??????// for process application deployments, job executor registration
??????// is managed by the ProcessApplicationManager
??????ProcessApplicationRegistration registration = registerProcessApplication(
??????????commandContext,
??????????deploymentToRegister,
??????????candidateDeployment,
??????????resourcesToIgnore.values());


??????return new ProcessApplicationDeploymentImpl(deploymentToRegister, registration);
????} else {
??????registerWithJobExecutor(commandContext, deploymentToRegister);
????}


????return deploymentToRegister;
??});


??createUserOperationLog(deploymentBuilder, deployment, commandContext);


??return deployment;
}


public <T> T runWithoutAuthorization(Callable<T> runnable) {
??CommandContext commandContext = Context.getCommandContext();
??boolean authorizationEnabled = commandContext.isAuthorizationCheckEnabled();
??try {
????commandContext.disableAuthorizationCheck();
????return runnable.call();
??} catch (RuntimeException e) {
????throw e;
??} catch (Exception e) {
????throw new ProcessEngineException(e);
??} finally {
????if (authorizationEnabled) {
??????commandContext.enableAuthorizationCheck();
????}
??}
}
代码调试发现,上面的代码就是部署流程的核心代码。
代码一步一步跟踪调试,终是没有发现解析参数的地方?上面的猜想失败了
那Camunda 到底是如何处理参数的呢?调试了好几天,都没有发现解析参数的地方!真的都被搞的很点失去信心了。
就在3月17日下午,我重新整理了调整了思路。
是不是直接从表里面查询出来的?
试试跟踪?runtimeService.getVariables(task.getExecutionId())?这个方法,终于发现了一点眉目,真是从表查询出来的。
public VariableMap execute(CommandContext commandContext) {
??ensureNotNull("executionId", executionId);


??ExecutionEntity execution = commandContext
????.getExecutionManager()
????.findExecutionById(executionId);


??ensureNotNull("execution " + executionId + " doesn't exist", "execution", execution);


??checkGetExecutionVariables(execution, commandContext);


??VariableMapImpl executionVariables = new VariableMapImpl();


??// collect variables from execution ?核心方法
??execution.collectVariables(executionVariables, variableNames, isLocal, deserializeValues);


??return executionVariables;
}

?

?

//?selectVariablesByExecutionId 对应执行的SQL语句
SELECT RES.*,
???????( case when RES.TASK_ID_ is not null and RES.EXECUTION_ID_ is not null then EXECUTION.ACT_INST_ID_
???????????when RES.CASE_EXECUTION_ID_ is not null then RES.CASE_EXECUTION_ID_ when EXECUTION.PARENT_ID_ is null
??????????and RES.IS_CONCURRENT_LOCAL_ = 0 then EXECUTION.ID_ when EXECUTION.IS_SCOPE_ = 1 and EXECUTION.PARENT_ID_ is not null
??????????and RES.IS_CONCURRENT_LOCAL_ = 0 then PARENT_EXECUTION.ACT_INST_ID_ else EXECUTION.ACT_INST_ID_ end ) ACT_INST_ID_
FROM ACT_RU_VARIABLE RES LEFT JOIN ACT_RU_EXECUTION EXECUTION ON RES.EXECUTION_ID_ = EXECUTION.ID_
????LEFT JOIN ACT_RU_EXECUTION PARENT_EXECUTION ON EXECUTION.PARENT_ID_ = PARENT_EXECUTION.ID_
WHERE EXECUTION_ID_ = '54854e59-a5c7-11ec-a5f8-92b1d713a145' AND TASK_ID_ is null
执行上面的SQL后,会返回?List<VariableInstanceEntity>?列表对象,在?VariableInstanceEntity?对象中有?ByteArrayField?属性,它保证的是 一条?ACT_GE_BYTEARRAY(保存的对象信息,也就是需要序列化的参数) 表的数据信息。
总结?runtimeService.getVariables 执行过程:
? ? 1、根据当前任务ID获取当?executionId,根据?executionId 查询?ACT_RU_VARIABLE 参数表
? ? 2、判断?ACT_RU_EXECUTION 表中的?PARENT_ID_ ?是否有值,有值就继续根据此值查询?ACT_RU_VARIABLE
? ? 3、 根据查询的 ?ACT_RU_VARIABLE 结果中?BYTEARRAY_ID_ 有值,就根据此ID去查询ACT_GE_BYTEARRAY 资源信息表,反序列化对象
?? ?
  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 21:22:01  更:2022-03-21 21:22:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 0:29:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码