前言碎语
以下内容为博主在公司内部分享的一个小文档,谈到了activiti的各方面内容,有需要的可留言要word原文件
Activiti工作流分享
分享或多或少都要有所收获,无论分享者或听众,大家聚在一起,集思广益,或收获一个关键字,一种新技术,一种新的理解,一种新的视角,分享的意义即在于此,下面,为了使分享的意义最大化,请允许我花一两分钟时间讲下和技术无关的题外话
受众分类
1.没用过没了解过的:我尽量事无巨细,点点讲清楚,有疑问,多问多提
2.了解过用过没深入的:突出详解api相关以及容器怎么加载activiti怎么设计怎么工作,还有activiti数据库表设计
3.用过熟知的:希望纠正错误的理解,补充没谈到的技术细节
关于文档:我会结合工程项目讲解,代码内容都在演示工程里,就不贴太多源码了,这里简要谈下,其实最好的文档就是官方文档啦
官方文档:http://www.activiti.org/userguide/index.html#
中文文档:http://www.kailing.pub/PdfReader/web/viewer.html?file=Activiti5.4Guide
进入正题:
activiti是什么?
是一种工作流引擎。提供对各应用系统有决定作用的根据角色、分工和条件的不同决定信息传递路由、内容等级等核心解决方案。工作流引擎包括了,流程的节点管理、流向管理、流程样例管理等重要功能
通俗点理解+使用场景举例:说白了,就是一个流程管理框架,使业务可以按照设定好的流程走,且可以在线更新业务流程,使程序可以快速适应业务变化发展,使系统更好的维护和扩展,解决了这么一个问题。具体场景的话如,借款审核,报销申报,请假审批等等
怎么集成,关键类,简单使用,ProcessEngineConfiguration相关实现解读?
ProcessEngineConfiguration 引擎配置类
org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration:此流程引擎用于独立环境下。Acitviti会处理事务。
org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration:适用于单元测试,Acitviti会处理事务。默认使用H2内存数据库。默认的databaseSchemaUpdat配置为DB_SCHEMA_UPDATE_CREATE_DROP,所以此数据库在流程引擎启动与关闭时进行创建和删除
org.activiti.spring.SpringProcessEngineConfiguration:Spring环境下使用流程引擎的情况下使用。
protected PlatformTransactionManager transactionManager; protected String deploymentName = "SpringAutoDeployment"; protected Resource[] deploymentResources = new Resource[0]; protected String deploymentMode = "default"; protected ApplicationContext applicationContext; protected Integer transactionSynchronizationAdapterOrder = null; private CollectiondeploymentStrategies = new ArrayList();
相比与官方提供的,spring的实现提供了更多的可配置项,如上,如部署资源数组,部署name,在获取引擎对象的时候,会自动部署我们配置的流程资源,可见如下buildProcessEngine方法的实现
@Override public ProcessEngine buildProcessEngine() { ProcessEngine processEngine = super.buildProcessEngine(); ProcessEngines.setInitialized(true); autoDeployResources(processEngine); return processEngine; } protected void autoDeployResources(ProcessEngine processEngine) { if (deploymentResources != null && deploymentResources.length > 0) { final AutoDeploymentStrategy strategy = getAutoDeploymentStrategy(deploymentMode); strategy.deployResources(deploymentName, deploymentResources, processEngine.getRepositoryService()); } }
引擎工具类ProcessEngines
ProcessEngines.getDefaultProcessEngine();
获取引擎
ProcessEngine processEngine = pec.buildProcessEngine();
基础服务类
RuntimeService runtimeService = processEngine.getRuntimeService(); RepositoryService repositoryService = processEngine.getRepositoryService(); TaskService taskService = processEngine.getTaskService(); ManagementService managementService = processEngine.getManagementService(); IdentityService identityService = processEngine.getIdentityService(); HistoryService historyService = processEngine.getHistoryService(); FormService formService = processEngine.getFormService();
手动部署流程
repositoryService.createDeployment().addClasspathResource("hello.bpmn").name("初级审核流程部署").deploy();
启动流程
runtimeService.startProcessInstanceByKey(String processDefinitionKey, Map variables);
任务查询
taskService.createTaskQuery().taskAssignee("boss").list();
处理人工任务
taskService. complete(String taskId, Mapvariables);
任务事件监听
TaskListener
Activiti工作原理之命令模式+职责链模式?
命令模式:行为请求者”与“行为实现者”相分离
职责链模式(责任链模式):参考filter实现,不多解释
org.activiti.engine.impl.interceptor包下五个关键接口或类
Command 实际命令
CommandConfig 命令执行配置,如事务级别配置
CommandExecutor命令执行器,最终命令执行,包含命令职责链
CommandInterceptor 命令拦截器链接口
CommandInvoker拦截器实现,链的最末端
从三处代码,详解看activiti如何设计
命令执行器如何初始化?
代码在org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl initCommandExecutors
protected void initCommandExecutors() { initDefaultCommandConfig(); initSchemaCommandConfig(); initCommandInvoker(); initCommandInterceptors(); initCommandExecutor(); }
1和2方法初始化了默认命令执行配置,主要用于事务拦截器命令执行,如SpringTransactionInterceptors事务拦截代码
public class SpringTransactionInterceptor extends AbstractCommandInterceptor { private static final Logger LOGGER = LoggerFactory.getLogger(SpringTransactionInterceptor.class); protected PlatformTransactionManager transactionManager; public SpringTransactionInterceptor(PlatformTransactionManager transactionManager) { this.transactionManager = transactionManager; } publicT execute(final CommandConfig config, final Commandcommand) { LOGGER.debug("Running command with propagation {}", config.getTransactionPropagation()); TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); transactionTemplate.setPropagationBehavior(getPropagation(config)); T result = transactionTemplate.execute(new TransactionCallback() { public T doInTransaction(TransactionStatus status) { return next.execute(config, command); } }); return result; } private int getPropagation(CommandConfig config) { switch (config.getTransactionPropagation()) {//判断CommandConfig配置 case NOT_SUPPORTED://无事务 return TransactionTemplate.PROPAGATION_NOT_SUPPORTED; case REQUIRED://默认是这个,无事务创建,有就加入 return TransactionTemplate.PROPAGATION_REQUIRED; case REQUIRES_NEW://无事务创建,有就将老事务挂起 return TransactionTemplate.PROPAGATION_REQUIRES_NEW; default: throw new ActivitiIllegalArgumentException("Unsupported transaction propagation: " + config.getTransactionPropagation()); } } }
这里谈到事务拦截器多讲一句,ProcessEngineConfigurationImpl类提供了一个抽象的获取事务拦截器的方法createTransactionInterceptor,其他引擎配置类可以重写这个抽象方法,提供自己的事务处理,如org.activiti.spring.SpringProcessEngineConfiguration引擎配置类处理如下:
@Override protected CommandInterceptor createTransactionInterceptor() { if (transactionManager == null) {//transactionManager是自己配置的 throw new ActivitiException("transactionManager is required property for SpringProcessEngineConfiguration, use " + StandaloneProcessEngineConfiguration.class.getName() + " otherwise"); } return new SpringTransactionInterceptor(transactionManager); }
3初始化命令执行者,也是一个拦截器,会被放在拦截器链的末端
4初始化拦截器,会添加用户自定义的前置拦截器集合(customPreCommandInterceptors)和后置拦截器集合(customPostCommandInterceptors),前置后后置是相对于activiti默认的拦截器来说的,可见如下代码,所以最后拦截器的顺序是:customPreCommandInterceptors->LogInterceptor->TransactionInterceptor->CommandContextInterceptor->customPostCommandInterceptors->commandInvoker
protected void initCommandInterceptors() { if (commandInterceptors==null) { commandInterceptors = new ArrayList(); if (customPreCommandInterceptors!=null) { commandInterceptors.addAll(customPreCommandInterceptors);//添加前置拦截 } commandInterceptors.addAll(getDefaultCommandInterceptors());//activiti默认 if (customPostCommandInterceptors!=null) { commandInterceptors.addAll(customPostCommandInterceptors); } commandInterceptors.add(commandInvoker); } } protected Collection< ? extends CommandInterceptor> getDefaultCommandInterceptors() { Listinterceptors = new ArrayList(); interceptors.add(new LogInterceptor()); CommandInterceptor transactionInterceptor = createTransactionInterceptor(); if (transactionInterceptor != null) { interceptors.add(transactionInterceptor); } interceptors.add(new CommandContextInterceptor(commandContextFactory, this)); return interceptors; }
5初始化命令执行器,包含了构建拦截器链的过程,可见代码如下
protected void initCommandExecutor() { if (commandExecutor==null) { CommandInterceptor first = initInterceptorChain(commandInterceptors); commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first); } } protected CommandInterceptor initInterceptorChain(Listchain) { if (chain==null || chain.isEmpty()) { throw new ActivitiException("invalid command interceptor chain configuration: "+chain); } for (int i = 0; i < chain.size()-1; i++) { chain.get(i).setNext( chain.get(i+1) ); } return chain.get(0); }
相关Service服务怎么执行?
public ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Mapvariables) { return commandExecutor.execute(new StartProcessInstanceCmd(processDefinitionKey, null, null, variables)); }
上面是runtimeService启动流程的方法内部结构,可以看到使用了commandExecutor提交了一个命令。也就是命令模式里面的行为请求者。你可能有疑问,那么命令执行器commandExecutor是何时注入的呢?请往下看
初始化服务
protected void initServices() { initService(repositoryService); initService(runtimeService); initService(historyService); initService(identityService); initService(taskService); initService(formService); initService(managementService); } protected void initService(Object service) { if (service instanceof ServiceImpl) { ((ServiceImpl)service).setCommandExecutor(commandExecutor); } }
最后安利一波设计模式,更高效阅读框架源码,细心的你可能发现了SpringProcessEngin eConfiguration中的自动部署用到了策略者模式,所以设计模式无处不在啊
24种设计模式:http://www.kailing.pub/PdfReader/web/viewer.html?file=24DesignPattern
流程设计简解
what启动事件和结束事件:?
what生产活动?
人工任务:需要人参与完成的工作。当流程执行到这样的用户任务时,会在分配任务的用户或用户组的任务列表中创建新的任务
服务任务:调用外部Java类
what网关?
并行网关(+):执行到该网关,会有多条线路同时并行执行,当都执行完才继续执行后面的;
排他网关(x):执行到该网关,根据条件只能走一条执行线路;
包容网关(o):整合并行网关+排他网关
更多其他流程图相关的内容怎么更好的学习?
建议画流程图的时候相关的节点多拖一拖看一看他的属性,结合文档摸索摸索就差不多了
数据表结构?
Activiti使用到的表都是ACT_开头的。
ACT_RE_*:’RE’表示repository(存储),RepositoryService接口所操作的表。带此前缀的表包含的是静态信息,如,流程定义,流程的资源(图片,规则等)。
ACT_RU_*:‘RU’表示runtime,运行时表-RuntimeService。这是运行时的表存储着流程变量,用户任务,变量,职责(job)等运行时的数据。Activiti只存储实例执行期间的运行时数据,当流程实例结束时,将删除这些记录。这就保证了这些运行时的表小且快。
ACT_ID_*:’ID’表示identity (组织机构),IdentityService接口所操作的表。用户记录,流程中使用到的用户和组。这些表包含标识的信息,如用户,用户组,等等。
ACT_HI_*:’HI’表示history,历史数据表,HistoryService。就是这些表包含着流程执行的历史相关数据,如结束的流程实例,变量,任务,等等
ACT_GE_*:全局通用数据及设置(general),各种情况都使用的数据。
详细说明每张表:
ACT_EVT_LOG 事件日志
ACT_GE_BYTEARRY xml, png等二进制内容
ACT_GE_PROPERTY 引擎版本信息
ACT_HI_ACTINST 历史节点
ACT_HI_ATTACHMENT 历史附件
ACT_HI_COMMENT 历史意见表
ACT_HI_DETAIL 历史详情表,提供历史变量的查询
ACT_HI_IDENTITYLINK 历史参与者
ACT_HI_PROCINST 历史流程实例
ACT_HI_TASKINST 历史任务实例
ACT_HI_VARINST 历史变量实例
ACT_ID_GROUP 用户组信息表
ACT_ID_INFO 用户的人员详细信息
ACT_ID_MEMBERSHIP 用户与群组关系
ACT_ID_USER 用户的基本信息
ACT_PROCDEF_INFO 流程定义的动态变更信息
ACT_RE_DEPLOYMENT 部署信息表
ACT_RE_MODEL 模型(用于Web Designer)
ACT_RE_PROCDEF 流程定义数据
ACT_RE_EVENT_SUBSCR 事件监听
ACT_RU_EXECUTION 流程实例
ACT_RU_IDENTITYLINK 参与者
ACT_RU_JOB 异步作业
ACT_RU_TASK 任务节点
ACT_RU_VARIABLE 流程变量
(彩蛋)Spring boot集成activiti,activiti rest服务?
参考另一篇博文:http://www.kailing.pub/article/index/arcid/137.html
最后的最后,深入浅出用一张图片做总结