环境: Spring-boot 嵌入式开发 、Canmunda版本7.16.0 、Canmunda依赖 camunda-bpm-spring-boot-starter
首先需要熟悉Camunda几个概念:
1. 部署(deploy/deployment):Camunda文档——processes.xml#流程应用程序部署
- 部署意味着一个Camunda程序的启动,向数据库中注册自己,并上传自身的流程定义文件
- 在processes.xml文件中,一个
<process-archive>
定义意味着一次部署(源码位置org.camunda.bpm.container.impl.deployment.DeployProcessArchivesStep
),如果processes.xml文件全空,则会填充默认配置(源码位置org.camunda.bpm.container.impl.deployment.ParseProcessesXmlStep
、org.camunda.bpm.application.impl.metadata.spi.ProcessesXml#EMPTY_PROCESSES_XML
)。process-archive的name属性不为空时,作为部署的Name属性(数据库字段ACT_RE_DEPLOYMENT#NAME_
)。Name留空(默认配置留空)时,部署名采用注解@EnableProcessApplication("appName")
否则为spring程序名@Value("${spring.application.name:null}")
(源码位置org.camunda.bpm.application.AbstractProcessApplication#getName
)
2. 恢复/激活部署(resumed/activate)与注册(register):文档同上,建议看源码注释(org.camunda.bpm.engine.ManagementService
)
- 恢复部署意味着激活一个Camunda应用(ProcessApplication),流程引擎(根据架构选择,流程引擎可能是外部的、共享的,又或者和应用同时启动)将在此应用中执行工作,作业处理器(job executor)也开始获取属于这个部署的流程作业。(如果一个部署没有被激活,属于该部署id的流程定义的流程实例可能无法正常工作——比如具有调用额外java类和资源的流程将无法执行)
- 当应用程序重启时,会自动发起部署(源码位置
org.camunda.bpm.container.impl.deployment.DeployProcessArchiveStep#performOperationStep
) 根据部署名(通常也就是process-archive name)查找最近版本部署,然后按byte对比两次部署的资源(.bpmn文件)差异(源码位置org.camunda.bpm.engine.impl.cmd.DeployCmd#resolveResourcesToDeploy
、org.camunda.bpm.engine.repository.DeploymentHandler#shouldDeployResource
),如果完全相同,视为同一个部署,则会恢复部署,若果有差异,则连同所有的流程定义(.bpmn)文件部署一个新版本的同名部署。 - 根据
<property name="isResumePreviousVersions">true</property>
(默认)和<property name="resumePreviousBy">process-definition-key</property>
(默认)(源码位置org.camunda.bpm.container.impl.deployment.DeployProcessArchiveStep#enableResumingOfPreviousVersions
、org.camunda.bpm.engine.impl.cmd.DeployCmd#registerProcessApplication
) 会自动恢复以前的部署,process-definition-key
意味着根据这次部署中所有的流程定义,所有包含具有相同processKey的流程定义(只包含一部分也算)的部署都将恢复。deployment-name
则意味着所有同名部署都会恢复。
3. isDeployChangedOnly
:资源过滤
<property name="isDeployChangedOnly">false</property>
(默认)- 此属性指示是否只应将与最新同名部署不同的资源作为部署的一部分,开启时,会拉取同名最新部署的同名资源进行比较,如果资源有一个byte不同,或者以前的部署没有同名资源才会放入部署列表
- 根据官网文件档,指示此属性包含副作用,会影响自动恢复部署,但是在源码
org.camunda.bpm.engine.impl.cmd.DeployCmd#getProcessDefinitionsFromResources
中,将排除的资源也加入了恢复部署的列表(?) - 如果开启了此属性,则需要特别小心
CallActivity
的流程步骤,此功能会将新流程与旧流程分隔为两个版本的部署,流程调用中如果绑定方式设为部署,则被调用的流程定义与调用流程定义因为以部署id绑定,可能需要属于同一部署名且同一版本的部署(尚未验证),故绑定方式应设为latest或version(旧版本部署肯定会被恢复/激活/注册,尚未验证旧版本也被恢复/激活/注册的情况下这种调用能不能横跨部署版本)
Java代码动态生成工作流流程定义:
Camunda文档 BPMN API
Camunda文档 Fluent BPMN Builder API
1.原始Api :(搬运官网案例)
1 | java复制代码// 创建一个空模型 |
1.Fluent Api :(搬运官网案例)
1 | java复制代码BpmnModelInstance modelInstance = Bpmn.createProcess() |
注意点:
节点id必须是合法的Xml NCName,且不能包含汉字、”-“
判断是否汉字用正则表达式,判断是否 Xml NCName 使用:com.sun.org.apache.xerces.internal.util.XMLChar#isValidNCName
注意此函数被idea提示为内部函数,jdk1.8以后不能保证存在
1 | java复制代码 private static void validXmlChar(String str) { |
部署生成的流程定义:
ProcessEngine 各种Service 的 Bean 声明在org.camunda.bpm.engine.spring.SpringProcessEngineServicesConfiguration
部署时候的配置参考org.camunda.bpm.container.impl.deployment.DeployProcessArchiveStep#performOperationStep
1 | java复制代码@Service |
需要注意的点是:
- 如果部署不指定name,则会生成name为NULL的部署
- 如果部署时不开启资源过滤(
.enableDuplicateFiltering(true/false)
),则每次部署都是新部署(虽然以更新流程为目标时,也必然是新部署就是了) - 没有特别需要不必开启 isDeployChangedOnly (
.enableDuplicateFiltering(true)
) - 尚不确定是否需要在部署新流程时包含旧流程定义(更新式部署),但是按照一般性思路,更新流程文件通常是修改jar包 Resources文件夹内的.bpmn文件,然后打包重新发布,最好模拟这个流程,在更新流程文件的部署时,包含除了需要修改的流程文件以外旧部署的其他流程文件(但是如果存在运行时修改或者创建流程定义的情况,就需要下面的方案👇)
- 在运行过程中添加或修改的流程,如果程序重新启动,就不会被包含在启动时部署的流程中(如果启动时不包含任何流程byte甚至不会执行部署),需要在流程启动时的部署中添加原有部署的资源:
我这里直接顶替掉SpringBootProcessApplication
,这样@EnableProcessApplication
注解也用不加了
1 | java复制代码@Configuration(proxyBeanMethods = false) |
根据 DeployProcessArchiveStep、DeployCmd的源码,程序部署的流程是
- 程序启动,准备部署
- 查看部署是否含有资源(
if(!deploymentResourceNames.isEmpty())
)- 无资源直接打个日志,不部署了
- DeployCmd开始部署
- 下载部署资源的远程资源(
DeployCmd#getResources()
) - 从资源中解析需要部署的资源(
DeployCmd#resolveResourcesToDeploy()
)- 如果全部资源都与数据库中最新同名部署资源全部一致,就判断为重复部署
- 重复部署,根据部署名查找最新部署id(
DefaultDeploymentHandler#determineDuplicateDeployment()
) - 根据id从数据库获取
DeploymentEntity
,将其注册
- 是新部署,往数据库插入数据,然后将其注册
本文转载自: 掘金