一、 安装和使用
安装和使用Flowable需要先下载相应版本的Flowable,可以从官方网站、github等获取,然后解压后就可以开始使用。一般来说,使用Flowable分为三个主要步骤:1)建模工作流, 2)部署工作流,3)执行工作流
二、 工作流引擎核心模块
Flowable工作流引擎的核心模块包括:1)启动子模块,这个模块负责加载其他模块并启动工作流引擎,2)存储子模块,负责管理工作流数据,3)运行时子模块,这个子模块负责提供运行时服务(例如任务分配、事件拦截器、作业操作等)
三、 启动流程实例
启动工作流引擎以及启动工作流实例是Flowable的重要特性。启动工作流实例是以一个定义好的BPMN 2.0 flow文件为模板来实现运行时流程能力的。在Flowable中,提供了多种启动流程实例的方式,如通过key启动、通过process definition id启动等。
// 1. 获取runtimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 2. 通过流程定义ID(key)来启动流程实例
ProcessInstance instance = runtimeService.startProcessInstanceByKey("process_key");
四、 用户任务
用户任务是面向用户的任务,需要手动完成。Flowable提供了一系列API来帮助程序员处理任务。在任务管理中,常见的操作包括:1)查询待办任务,2)领取任务,3)完成任务
// 1. 获取TaskService
TaskService taskService = processEngine.getTaskService();
// 2. 获取任务查询对象
TaskQuery query = taskService.createTaskQuery();
// 3. 查询指派给当前用户的所有任务
query.taskAssignee("当前用户ID");
// 获取任务列表
List<Task> taskList = query.list();
// 完成任务
Task task = taskList.get(0);
taskService.complete(task.getId());
五、 定时器
定时器在Flowable中可以被称之为作业,在一个工作流程中,发生的所有事件都是非常重要的,当发生事件时,Flowable需要在特定的时间触发相应的操作。Flowable提供了一种适用于异步事件处理的调度模式,这种模式基于Java Timer和Spring Task。 在Flowable中,定时器由“Timer Event”元素提供,可安排计划来调度任务的运行。在处理内存资源紧张的情况下,Flowable定时器支持异步处理事件,使轻量的流程引擎可以在决策期间执行长时间运行的操作。
// 1. 通过JobExecutor注册定时器Service
JobExecutor jobExecutor = new JobExecutor();
FlowableScheduler bpmnScheduler = new BpmnJobScheduler(jobExecutor);
processEngineConfiguration.setBpmnJobExecutor(jobExecutor);
// 2. 添加定时器事件
TimerEventDefinition timerEventDefinition = eventDefs[0].querySingle("timerEventDefinition");
Definitions defs = rootElement.querySingle("definitions");
Process process = defs.querySingle("process");
UserTask task = process.querySingle("userTask");
BoundaryEvent boundaryEvent = task.getBoundaryEvent();
boundaryEvent.setAttachedToRef(task.getId());
boundaryEvent.setValues(flowJsonDelegate);
EventSubscriptionEntity subscriptionEntity = (EventSubscriptionEntity) runtimeService.createEventSubscriptionQuery()
.eventType(TimerEventEntity.EVENT_TYPE)
.processInstanceId(instance.getId())
.activityId(task.getId())
.singleResult();
// 启动定时器
bpmnScheduler.schedule(new TimerEventHandler(subscriptionEntity));
六、事件拦截器
事件拦截器是Flowable流程引擎中实现AOP机制的一种方式。它为业务程序操作提供了一些手段来对流程状态进行观察和控制。流程执行过程中的各种事件事件(任务分配、任务开始、任务完成等)都会被拦截并分发到相应的事件监听器中。 通过配置相关的事件监听器来确定拦截器将生成哪些事件,然后将这些事件与其他业务逻辑相结合,来实现对流程执行的控制。
public class CustomProcessEngineConfiguration extends StandaloneProcessEngineConfiguration {
@Override
public EventDispatcher getEventDispatcher() {
if (getCustomEventDispatchers().isEmpty()) {
return super.getEventDispatcher();
} else {
EventDispatcherImpl eventDispatcher = new EventDispatcherImpl(getClock(), getExecutionListeners(), getTaskListeners(),
createEventListenerGroups(), getCustomEventDispatchers());
eventDispatcher.setAsyncExecutor(asyncExecutor);
return eventDispatcher;
}
}
protected Map<String, EventDispatcher> getCustomEventDispatchers() {
return customEventDispatchers;
}
}
EventDispatcher dispatcher = ((ProcessEngineImpl) processEngine).getProcessEngineConfiguration().getEventDispatcher();
List<EventDispatcher> eventDispatchers = new ArrayList<>();
eventDispatchers.add(dispatcher);
CustomProcessEngineConfiguration config = new CustomProcessEngineConfiguration();
config.setCustomEventDispatchers(eventDispatchers);
ProcessEngine engine = config.buildProcessEngine();
七、 数据库锁定机制
在多用户环境下,为了防止并发问题,需要使用特殊技术来控制数据访问,例如:乐观锁和悲观锁。Flowable引擎通过使用基于文件锁的乐观锁机制来管理实例访问,这种机制可以确保数据的一致性,同时也保证了较高的并发性和可扩展性。
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="processSessionFactory" class="org.apache.ibatis.session.defaults.DefaultSqlSessionFactory">
<constructor-arg ref="processDataSource"/>
<property name="configuration" ref="processConfiguration"/>
</bean>
<bean id="processConfiguration" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="org.flowable.engine.mappers" />
<property name="processDataSource" ref="processDataSource" />
<property name="processSessionFactory" ref="processSessionFactory" />
<property name="sqlSessionFactoryBeanName" value="processSessionFactory" />
</bean>