Snaker工作流学习(三)

Snaker工作流学习(三)目录前言三 API 及详细说明 1 数据表说明 2 Snaker 引擎接口 3 模型 4 流程定义 5 流程实例 6 活动任务 7 流程变量 8 任务参与者 9 拦截器 10 委托代理 11 时限控制 12 选择分支 13

大家好,欢迎来到IT知识分享网。

前言

Snaker是基于java的轻量级工作流引擎,接口丰富,使用简单。

三、API及详细说明
1、数据表说明

Snaker流程引擎常用表共9张,其中前7张为核心表:

表名称 描述
wf_process 流程定义表
wf_order 活动实例表
wf_task 活动任务表
wf_task_actor 活动任务参与者表
wf_hist_order 历史实例表
wf_hist_task 历史任务表
wf_hist_task_actor 历史任务参与者表
wf_surrogate 委托代理管理表
wf_cc_order 抄送实例表

各表字段说明

  • wf_process
字段名称 字段描述
id 主键ID
parent_Id 父流程ID
process_Id 流程定义ID
creator 发起人
create_Time 发起时间
expire_Time 期望完成时间
last_Update_Time 上次更新时间
last_Updator 上次更新人
priority 优先级
parent_Node_Name 父流程依赖的节点名称
order_No 流程实例编号
variable 附属变量json存储
version 版本
  • wf_order
字段名称 字段描述
id 主键ID
parent_Id 父流程ID
process_Id 流程定义ID
creator 发起人
create_Time 发起时间
expire_Time 期望完成时间
last_Update_Time 上次更新时间
last_Updator 上次更新人
priority 优先级
parent_Node_Name 父流程依赖的节点名称
order_No 流程实例编号
variable 附属变量json存储
version 版本
  • wf_hist_order
字段名称 字段描述
id 主键ID
parent_id 父流程ID
process_id 流程定义ID
creator 发起人
create_time 发起时间
expire_time 期望完成时间
end_time 完成时间
priority 优先级
order_no 流程实例编号
variable 附属变量json存储
order_state 状态
  • wf_task
字段名称 字段描述
id 主键ID
order_Id 流程实例ID
task_Name 任务名称
display_Name 任务显示名称
task_Type 任务类型
perform_Type 参与类型
operator 任务处理人
create_Time 任务创建时间
finish_Time 任务完成时间
expire_Time 任务期望完成时间
action_Url 任务处理的url
parent_Task_Id 父任务ID
variable 附属变量json存储
version 版本
  • wf_hist_task
字段名称 字段描述
id 主键ID
order_Id 流程实例ID
task_Name 任务名称
display_Name 任务显示名称
task_Type 任务类型
perform_Type 参与类型
operator 任务处理人
create_Time 任务创建时间
finish_Time 任务完成时间
expire_Time 任务期望完成时间
action_Url 任务处理的url
parent_Task_Id 父任务ID
variable 附属变量json存储
task_State 任务状态
  • wf_task_actor
字段名称 字段描述
task_Id 任务ID
actor_Id 参与者ID
  • wf_hist_task_actor
字段名称 字段描述
task_Id 任务ID
actor_Id 参与者ID
  • wf_surrogate
字段名称 字段描述
id 主键ID
process_Name 流程名称
operator 授权人
surrogate 代理人
odate 操作时间
sdate 开始时间
edate 结束时间
state 状态
  • wf_cc_order
字段名称 字段描述
order_Id 流程实例ID
actor_Id 参与者ID
create_Time 抄送时间
finish_Time 完成时间
creator 发起人
status 状态
2、Snaker引擎接口
org.snaker.engine.SnakerEngine 

所有服务的入口,提供获取服务的方法,同时也提供最常用的API接口

  • 三个静态属性
public static final String ADMIN = "snaker.admin"; public static final String AUTO = "snaker.auto"; public static final String ID = "snaker.orderNo"; 
  • 配置业务实现
/ * 根据Configuration对象配置实现类 * @param config 全局配置对象 * @return SnakerEngine 流程引擎 */ public SnakerEngine configure(Configuration config); 
  • 获取流程定义服务
public IProcessService process(); 
  • 获取实例服务
public IOrderService order(); 
  • 获取任务服务
public ITaskService task(); 
  • 获取查询服务
public IQueryService query(); 
  • 获取管理服务
public IManagerService manager(); 
  • 根据流程定义ID启动流程实例
/ * 根据流程定义ID、操作人ID、参数列表启动流程实例 * @param id 流程定义ID * @param operator 操作人ID * @param args 参数列表 * @return Order 流程实例 */ public Order startInstanceById(String id); public Order startInstanceById(String id, String operator); public Order startInstanceById(String id, String operator, Map<String, Object> args); 
  • 根据流程名称启动流程实例
/ * 根据流程名称、版本号、操作人、参数列表启动流程实例 * @param name 流程定义名称 * @param version 版本号 * @param operator 操作人 * @param args 参数列表 * @return Order 流程实例 */ public Order startInstanceByName(String name); public Order startInstanceByName(String name, Integer version); public Order startInstanceByName(String name, Integer version, String operator); public Order startInstanceByName(String name, Integer version, String operator, Map<String, Object> args); 
  • 根据父执行对象启动子流程实例
/ * 根据父执行对象启动子流程实例 * @param execution 执行对象 * @return Order 流程实例 */ public Order startInstanceByExecution(Execution execution); 
  • 执行任务
/ * 根据任务主键ID、操作人ID、参数列表执行任务 * @param taskId 任务主键ID * @param operator 操作人主键ID * @param args 参数列表 * @return List<Task> 任务集合 */ public List<Task> executeTask(String taskId); public List<Task> executeTask(String taskId, String operator); public List<Task> executeTask(String taskId, String operator, Map<String, Object> args); 
  • 跳转到任意节点
/ * 根据任务主键ID、操作人ID、参数列表执行任务,并且根据nodeName跳转到任意节点 * 1、nodeName为null时,则跳转至上一步处理 * 2、nodeName不为null时,则任意跳转,即动态创建转移 * @param taskId 任务主键ID * @param operator 操作人主键ID * @param args 参数列表 * @param nodeName 跳转的节点名称 * @return List<Task> 任务集合 */ public List<Task> executeAndJumpTask(String taskId, String operator, Map<String, Object> args, String nodeName); 
  • 创建新的自由任务
/ * 根据流程实例ID、操作人ID、参数列表按照节点模型model创建新的自由任务 * @param orderId 流程实例id * @param operator 操作人id * @param args 参数列表 * @param model 节点模型 * @return List<Task> 任务集合 */ public List<Task> createFreeTask(String orderId, String operator, Map<String, Object> args, TaskModel model); 
3、模型
  • 模型元素基类
org.snaker.engine.model.BaseModel 
  • 流程定义元素模型
org.snaker.engine.model.ProcessModel 
  • 变迁定义元素模型
org.snaker.engine.model.TransitionModel 
  • 字段模型
org.snaker.engine.model.FieldModel 
  • 节点元素模型
org.snaker.engine.model.NodeModel 
  • 开始节点元素模型
org.snaker.engine.model.StartModel 
  • 决策定义元素模型
org.snaker.engine.model.DecisionModel 
  • 分支定义元素模型
org.snaker.engine.model.ForkModel 
  • 合并定义元素模型
org.snaker.engine.model.JoinModel 
  • 结束节点元素模型
org.snaker.engine.model.EndModel 
  • 工作元素模型
org.snaker.engine.model.WorkModel 
  • 任务定义元素模型
org.snaker.engine.model.TaskModel 
  • 子流程定义元素模型
org.snaker.engine.model.SubProcessModel 
  • 自定义模型
org.snaker.engine.model.CustomModel 
4、流程定义
org.snaker.engine.IProcessService 

流程定义业务接口,服务设计使用缓存,默认是内存缓存,同时也支持ehcache缓存框架,只需要依赖snaker-ehcache包即可。

  • 检查流程定义对象
/ * 检查流程定义对象 * @param process 流程定义对象 * @param idOrName 流程定义id/name */ void check(Process process, String idOrName); 
  • 保存流程定义
/ * 保存流程定义 * @param process 流程定义对象 */ void saveProcess(Process process); 
  • 更新流程定义的类别
/ * 更新流程定义的类别 * @param id 流程定义id * @param type 类别 */ void updateType(String id, String type); 
  • 获取流程定义对象
/ * 根据主键ID获取流程定义对象 * @param id 流程定义id * @return Process 流程定义对象 */ Process getProcessById(String id); / * 根据流程name获取流程定义对象 * @param name 流程定义名称 * @return Process 流程定义对象 */ Process getProcessByName(String name); / * 根据流程name、version获取流程定义对象 * @param name 流程定义名称 * @param version 版本号 * @return Process 流程定义对象 */ Process getProcessByVersion(String name, Integer version); / * 根据给定的参数列表args查询process * @param filter 查询过滤器 * @return List<Process> 流程定义对象集合 */ List<Process> getProcesss(QueryFilter filter); / * 根据给定的参数列表args分页查询process * @param page 分页对象 * @param filter 查询过滤器 * @return List<Process> 流程定义对象集合 */ List<Process> getProcesss(Page<Process> page, QueryFilter filter); 
  • 部署流程定义

流程发布统一使用InputStream输入流作为流程定义的数据,可借助

org.snaker.engine.helper.StreamHelper 

流帮助类完成,方法如下定义:

InputStream的方法名称 描述
getStreamFromString 根据字符串获取输入流
getStreamFromFile 根据文件对象获取输入流
getStreamFromClasspath 根据类路径下的资源文件名称获取输入流
getStreamFromUrl 根据url远程资源获取输入流
//注意:snaker的流程定义编码格式统一使用UTF-8 
/ * 根据InputStream输入流,部署流程定义 * @param input 流程定义输入流 * @param creator 创建人 * @return String 流程定义id */ String deploy(InputStream input); String deploy(InputStream input, String creator); / * 根据InputStream输入流,部署流程定义 * @param id 流程定义id * @param input 流程定义输入流 */ void redeploy(String id, InputStream input); 
  • 卸载流程定义
/ * 卸载指定的流程定义,只更新状态 * @param id 流程定义id */ void undeploy(String id); 
  • 级联删除指定流程的所有数据
/ * 谨慎使用.数据恢复非常痛苦,你懂得~~ * 级联删除指定流程定义的所有数据: * 1.wf_process * 2.wf_order,wf_hist_order * 3.wf_task,wf_hist_task * 4.wf_task_actor,wf_hist_task_actor * 5.wf_cc_order * @param id */ void cascadeRemove(String id); 
5、流程实例
org.snaker.engine.IOrderService 

流程实例业务接口,配合流程引擎完成流程实例的开始和结束。

  • 创建流程实例
/ * 根据流程、操作人员、父流程实例ID创建流程实例 * @param process 流程定义对象 * @param operator 操作人员ID * @param args 参数列表 * @param parentId 父流程实例ID * @param parentNodeName 父流程节点模型 * @return Order 活动流程实例对象 */ Order createOrder(Process process, String operator, Map<String, Object> args); Order createOrder(Process process, String operator, Map<String, Object> args, String parentId, String parentNodeName); 
  • 添加全局变量数据
/ * 向指定实例id添加全局变量数据 * @param orderId 实例id * @param args 变量数据 */ void addVariable(String orderId, Map<String ,Object> args); 
  • 创建抄送实例
/ * 创建抄送实例 * @param orderId 流程实例id * @param actorIds 参与者id * @param creator 创建人id * @since 1.5 */ void createCCOrder(String orderId, String creator, String... actorIds); 
  • 流程实例正常完成
/ * 流程实例正常完成 * @param orderId 流程实例id */ void complete(String orderId); 
  • 保存流程实例
/ * 保存流程实例 * @param order 流程实例对象 */ void saveOrder(Order order); 
  • 流程实例强制终止
/ * 流程实例强制终止 * @param orderId 流程实例id * @param operator 处理人员 */ void terminate(String orderId); void terminate(String orderId, String operator); 
  • 唤醒历史流程实例
/ * 唤醒历史流程实例 * @param orderId 流程实例id * @return 活动实例对象 */ Order resume(String orderId); 
  • 更新流程实例
/ * 更新流程实例 * @param order 流程实例对象 */ void updateOrder(Order order); 
  • 更新抄送记录为已阅
/ * 更新抄送记录为已阅 * @param orderId 流程实例id * @param actorIds 参与者id */ void updateCCStatus(String orderId, String... actorIds); 
  • 删除抄送记录
/ * 删除抄送记录 * @param orderId 流程实例id * @param actorId 参与者id */ void deleteCCOrder(String orderId, String actorId); 
  • 级联删除
/ * 谨慎使用.数据恢复非常痛苦,你懂得~~ * 级联删除指定流程实例的所有数据: * 1.wf_order,wf_hist_order * 2.wf_task,wf_hist_task * 3.wf_task_actor,wf_hist_task_actor * 4.wf_cc_order * @param id */ void cascadeRemove(String id); 
6、活动任务

org.snaker.engine.ITaskService

任务业务接口

  • 完成任务
/ * 完成指定的任务,删除活动任务记录,创建历史任务 * @param taskId 任务id * @param operator 操作人id * @param args 参数集合 * @return Task 任务对象 */ Task complete(String taskId); Task complete(String taskId, String operator); Task complete(String taskId, String operator, Map<String, Object> args); 
  • 更新任务对象
/ * 更新任务对象 * @param task 任务对象 */ void updateTask(Task task); 
  • 创建历史任务记录
/ * 根据执行对象、自定义节点模型创建历史任务记录 * @param execution 执行对象 * @param model 自定义节点模型 * @return 历史任务 */ HistoryTask history(Execution execution, CustomModel model); 
  • 提取任务
/ * 根据任务主键ID,操作人ID提取任务 * 提取任务相当于预受理操作,仅仅标识此任务只能由此操作人处理 * @param taskId 任务id * @param operator 操作人id * @return Task 任务对象 */ Task take(String taskId, String operator); 
  • 唤醒历史任务
/ * 根据历史任务主键id,操作人唤醒历史任务 * 该方法会导致流程状态不可控,请慎用 * @param taskId 历史任务id * @param operator 操作人id * @return Task 唤醒后的任务对象 */ Task resume(String taskId, String operator); 
  • 添加参与者
/ * 向指定的任务id添加参与者 * @param taskId 任务id * @param performType 参与类型 * @param actors 参与者 */ void addTaskActor(String taskId, String... actors); void addTaskActor(String taskId, Integer performType, String... actors); 
  • 删除参与者
/ * 对指定的任务id删除参与者 * @param taskId 任务id * @param actors 参与者 */ void removeTaskActor(String taskId, String... actors) 
  • 撤回任务
/ * 根据任务主键id、操作人撤回任务 * @param taskId 任务id * @param operator 操作人 * @return Task 任务对象 */ Task withdrawTask(String taskId, String operator); 
  • 驳回任务
/ * 根据当前任务对象驳回至上一步处理 * @param model 流程定义模型,用以获取上一步模型对象 * @param currentTask 当前任务对象 * @return Task 任务对象 */ Task rejectTask(ProcessModel model, Task currentTask); 
  • 判断操作人是否允许执行任务
/ * 根据taskId、operator,判断操作人operator是否允许执行任务 * @param task 任务对象 * @param operator 操作人 * @return boolean 是否允许操作 */ boolean isAllowed(Task task, String operator); 
  • 创建新的任务
/ * 根据任务模型、执行对象创建新的任务 * @param taskModel 任务模型 * @param execution 执行对象 * @return List<Task> 创建任务集合 */ List<Task> createTask(TaskModel taskModel, Execution execution); / * 根据已有任务id、任务类型、参与者创建新的任务 * @param taskId 主办任务id * @param taskType 任务类型 * @param actors 参与者集合 * @return List<Task> 创建任务集合 */ List<Task> createNewTask(String taskId, int taskType, String... actors); 
  • 获取任务模型
/ * 根据任务id获取任务模型 * @param taskId 任务id * @return */ TaskModel getTaskModel(String taskId); 
7、流程变量

全局变量数据,各接口方法参数集合Map<String, Object> args,对应于数据表的variable,可根据需要修改添加,若不改不加可传null

8、任务参与者

Snaker的任务参与者有三种设置方式:

  • 静态配置

在流程设计时设置,为标签的assignee属性赋值为用户id、部门id、组id等。

  • 动态传递

在流程设计时设置,为标签的assignee属性赋值为变量名,然后在调用流程引擎时通过参数集合传递,即设置流程变量。

  • 自定义类处理

通过自定义类[继承Assignment类],设置assignmentHandler属性,assign方法返回值就是参与者

  • 注:

1)动态添加删除参与者可参照活动任务的addTaskActor和removeTaskActor方法;

2)组支持

由于snaker引擎与用户权限完全解耦的,所以对于组的支持,仅仅是你设置组作为参与者,你就要自定义一个任务的访问策略,能够根据操作人得到所有的组集合,这样流程引擎才能允许该操作人处理任务。

自定义任务访问策略类

public class CustomAccessStrategy extends GeneralAccessStrategy { 
    protected List<String> ensureGroup(String operator) { 
    //此处根据实际项目获取操作人对应的组列表 return ShiroUtils.getGroups(); } } 

在snaker.xml中增加下面的配置

<bean class="com.snakerflow.framework.flow.CustomAccessStrategy"/> 
9、拦截器

Snaker的拦截器支持所有的节点前后拦截,并且支持全局、局部拦截器。拦截器统一实现SnakerInterceptor接口。

org.snaker.engine.SnakerInterceptor 
  • 全局拦截器

全局拦截器会拦截所有新产生的任务对象,自定义的全局拦截器需要配置到snaker.xml中,如默认支持的日志拦截器。

<bean class="org.snaker.engine.impl.LogInterceptor"/> 
  • 局部拦截器

局部拦截器支持节点执行的前置、后置拦截,需要配置到task节点模型的preInterceptors[前置拦截]、postInterceptors[后置拦截]属性。

10、委托代理

Snaker支持委托他人代理处理任务。

  • 委托代理配置

需要在snker.xml中配置委托代理的拦截器

<bean class="org.snaker.engine.impl.SurrogateInterceptor"/> 
  • 管理委托代理

委托代理的数据管理由管理服务类完成

org.snaker.engine.IManagerService 

管理服务接口针对委托代理提供以下方法:

/ * 保存或更新委托代理对象 * @param surrogate 委托代理对象 */ public void saveOrUpdate(Surrogate surrogate); / * 删除委托代理对象 * @param id 委托代理主键id */ public void deleteSurrogate(String id); / * 根据主键id查询委托代理对象 * @param id 主键id * @return surrogate 委托代理对象 */ public Surrogate getSurrogate(String id); / * 根据过滤条件查询委托代理对象 * @param filter 查询过滤器 * @return List<Surrogate> 委托代理对象集合 */ public List<Surrogate> getSurrogate(QueryFilter filter); / * 根据授权人、流程名称获取最终代理人 * 如存在user1->user2->user3,那么最终返回user3 * @param operator 授权人 * @param processName 流程名称 * @return String 代理人 */ public String getSurrogate(String operator, String processName); / * 根据过滤条件查询委托代理对象 * @param page 分页对象 * @param filter 查询过滤器 * @return List<Surrogate> 委托代理对象集合 */ public List<Surrogate> getSurrogate(Page<Surrogate> page, QueryFilter filter); 
11、时限控制

时限控制常用于流程平台中的超时处理(提醒、自动执行等)、以及任务监控的查询统计等功能,Snaker默认支持quartz定时器调度框架,只需要依赖snaker-quartz的包即可。

  • 配置

snaker.xml中配置时限控制的拦截器、定时调度的实现类

<bean class="org.snaker.engine.impl.SchedulerInterceptor"/> <bean class="org.snaker.engine.scheduling.quartz.QuartzScheduler"/> 

如果使用其它定时调度框架,需要实现IScheduler接口,并替换QuartzScheduler类配置

以上两步已经完成了时限的配置工作,下面就可以针对提醒、超时自动执行做自定义扩展了。

  • 超时提醒

编写自定义的提醒类,实现IReminder接口。并配置到snaker.xml中即可;任务节点配置超时提醒属性:reminderTimereminderRepeatreminderTime是一个变量,表示提醒开始时间,当你调用api时需要传递此变量值,值的类型为date;reminderRepeat是一个数字,表示重复提醒间隔时间,以分钟为单位。

默认提醒一次就结束,如果希望提醒多次,可通过snaker.properties中配置scheduler.repeat属性,该值是个数字,表示提醒次数。

#节假日配置 #是否启用节假日,默认为false scheduler.useCalendar=true/false #节日配置,格式为yyyy-MM-dd,... scheduler.holidays=2014-12-26,2014-12-27 #工作日设置,格式为1,2,3...7,表示周一至周日 scheduler.weeks=1,2,3,4,5 #工作时间设置,格式为8:00-18:00 scheduler.workTime=8:00-18:00 
  • 超时自动完成

任务节点配置超时处理属性:expireTimeautoExecutecallbackexpireTime是一个变量,表示期望完成时间,当你调用api时需要传递此变量值,值的类型为date;autoExecute的值为Y/N,表示超时是否自动执行,一般在流程设计时配置完成;callback是一个字符串,表示自动执行的回调类路径配置,回调类通过实现JobCallback接口。

org.snaker.engine.scheduling.JobCallback 
12、选择分支

Snaker的decision(选择分支)节点支持三种路由选择方式:

  • decision的expr

decision节点的expr有两种方式来设置

1.表达式中增加判断逻辑,如:${day > 3 ? 't1' : 't2'},此时根据day的值决定走t1、或t2的路由,用于设置范围值的情况 2.表达式仅仅是一个变量,如:${tname},此时,传递tname的值为路由name即可,用于设置具体值的情况(如:同意、不同意) 
  • transition的expr

如果decision节点的expr为空,可设置输出路由的expr,必须返回boolean类型

路由1设置expr的值为:${content==1}, 路由2设置expr的值为${content > 1}。 
  • 自定义类

自定义类需要实现DecisionHandler接口的decide方法

org.snaker.engine.DecisionHandler 

该方法返回字符串即表示输出路由的name

  • 注:决策表达式

Snaker默认支持JuelSringEL两种表达式引擎,需要在snaker.xml中配置。配置如下:

<bean class="org.snaker.engine.impl.JuelExpression"/> 

并且支持自定义表达式,实现Expression接口,同样修改一下配合即可。

Juel表达式引擎常用语法

String expr1 = "${content}"; Map<String, Object> args1 = new HashMap<String, Object>(); args1.put("content", 1); System.out.println(eval(String.class, expr1, args1)); String expr2 = "${content == 1 ? 'v1' : 'v2'}"; Map<String, Object> args2 = new HashMap<String, Object>(); //此处不仅支持数字类型,也支持字符串类型,但是值必须可转换为数字 args2.put("content", "2"); System.out.println(eval(String.class, expr2, args2)); String expr3 = "${content > 1 ? 'v1' : 'v2'}"; Map<String, Object> args3 = new HashMap<String, Object>(); //此处只要是数字类型即可,如1或0.5等 args3.put("content", 4.2); System.out.println(eval(String.class, expr3, args3)); //juel支持表达式为字符串类型而参数为数字类型 String expr4 = "${content == '1' ? 'v1' : 'v2'}"; Map<String, Object> args4 = new HashMap<String, Object>(); //此处不仅可以写字符串"1",也可以写char类型'1',写数字类型1,浮点类型1.00 args4.put("content", 1); System.out.println(eval(String.class, expr4, args4)); //逻辑表达式与,使用&&表示 String expr5 = "${content > 1 && content <= 10 ? 'v1' : 'v2'}"; Map<String, Object> args5 = new HashMap<String, Object>(); //此处不仅可以写字符串"1",也可以写char类型'1',写数字类型1,浮点类型1.00 args5.put("content", "11"); System.out.println(eval(String.class, expr5, args5)); //逻辑表达式或,使用||表示 String expr6 = "${content < 1 || content > 10 ? 'v1' : 'v2'}"; Map<String, Object> args6 = new HashMap<String, Object>(); //此处不仅可以写字符串"1",也可以写char类型'1',写数字类型1,浮点类型1.00 args6.put("content", "1"); System.out.println(eval(String.class, expr6, args6)); //逻辑表达式 String expr7 = "${content < 1 || content > 10 ? 'v1' : (content == 8 ? 'v2' : 'v3')}"; Map<String, Object> args7 = new HashMap<String, Object>(); //此处不仅可以写字符串"1",也可以写char类型'1',写数字类型1,浮点类型1.00 args7.put("content", "8"); System.out.println(eval(String.class, expr7, args7)); 

Spring EL表达式引擎常用语法

String expr1 = "#content"; Map<String, Object> args1 = new HashMap<String, Object>(); args1.put("content", "v2"); System.out.println(expr1 + "====>" + eval(String.class, expr1, args1)); String expr2 = "#content == 1 ? 'v1' : 'v2'"; Map<String, Object> args2 = new HashMap<String, Object>(); //此处仅支持数字类型 args2.put("content", 2.1); System.out.println(expr2 + "====>" + eval(String.class, expr2, args2)); String expr3 = "#content > 1 ? 'v1' : 'v2'"; Map<String, Object> args3 = new HashMap<String, Object>(); //此处只要是数字类型即可,如1或0.5等 args3.put("content", 4.2); System.out.println(expr3 + "====>" + eval(String.class, expr3, args3)); //spel支持表达式为字符串类型而参数为数字类型 String expr4 = "#content == '1' ? 'v1' : 'v2'"; Map<String, Object> args4 = new HashMap<String, Object>(); //此处仅支持字符串"1" args4.put("content", "1"); System.out.println(expr4 + "====>" + eval(String.class, expr4, args4)); //逻辑表达式与,使用and表示 String expr5 = "#content > 1 and #content <= 10 ? 'v1' : 'v2'"; Map<String, Object> args5 = new HashMap<String, Object>(); //此处仅支持数字类型 args5.put("content", 11); System.out.println(expr5 + "====>" + eval(String.class, expr5, args5)); //逻辑表达式或,使用||表示 String expr6 = "#content < 1 or #content > 10 ? 'v1' : 'v2'"; Map<String, Object> args6 = new HashMap<String, Object>(); //此处不仅可以写字符串"1",也可以写char类型'1',写数字类型1,浮点类型1.00 args6.put("content", 1); System.out.println(expr6 + "====>" + eval(String.class, expr6, args6)); //逻辑表达式 String expr7 = "(#content < 1 or #content > 10) ? 'v1' : (#content == 8 ? 'v2' : 'v3')"; Map<String, Object> args7 = new HashMap<String, Object>(); //此处不仅可以写字符串"1",也可以写char类型'1',写数字类型1,浮点类型1.00 args7.put("content", 8); System.out.println(expr7 + "====>" + eval(String.class, expr7, args7)); 
13、会签

Snaker的会签目前相对比较简单,仅仅是根据任务节点的performType属性值确定是否产生多个相同任务。

performType的值有两种,分别是ANYALL

ANY 多个参与者时,任何一个完成任务即继续流转

ALL 多个参与者时,所有都需要完成任务才能继续流转

  • fork/join

Snaker流程引擎中的所有节点模型都支持fork/join的并行流转。

14、子流程

子流程的作用是将一个复杂的业务流程进行细化拆分,提高流程的复用性

  • 子流程模型

子流程模型类型为SubProcessModel,其主要属性为processName,根据流程的name进行关联,由于流程定义支持一个name多个版本同时运行,那么子流程关联只设置name,即表示与最新版本的子流程关联。

  • 父子流程的关联

对于表结构的设计中,父子流程的关联字段为

wf_order[parent_Idparent_Node_Name]

wf_hist_order[parent_Id]

15、抄送

类似于邮箱里面的抄送功能,一般用于将该流程实例抄送给领导查阅。

  • 创建抄送

根据实例id、创建人、抄送人创建抄送记录

engine.order().createCCOrder(String orderId, String creator, String... actorIds) 
  • 更新状态

更新状态用于更新抄送记录为已经阅读

engine.order().updateCCStatus(String orderId, String... actorIds) 
16、自定义节点

Snaker的自定义节点可完成流程的全自动编排,只需要在自定义节点模型中配置处理类即可。

自定义节点的处理类有两种方式:

  • 实现IHandler接口

只需要配置clazz属性即可

  • 普通java类

需要设置clazz methodName args var

自定义节点的执行不需要外部触发,只要抵达节点立即执行绑定的类进行处理,并记录历史任务,处理类返回值保存在历史任务的变量字段中。

17、综合查询

综合查询服务不仅提供流程实例、活动/历史任务、待办任务的查询,同时支持原生SQL语句的查询服务。

org.snaker.engine.IQueryService //根据流程实例ID获取流程实例对象 Order getOrder(String orderId); //根据流程实例ID获取历史流程实例对象 HistoryOrder getHistOrder(String orderId); //根据任务ID获取任务对象 Task getTask(String taskId); //根据任务ID获取历史任务对象 HistoryTask getHistTask(String taskId); //根据任务ID获取活动任务参与者数组 String[] getTaskActorsByTaskId(String taskId); //根据任务ID获取历史任务参与者数组 String[] getHistoryTaskActorsByTaskId(String taskId); //根据filter查询活动任务 List<Task> getActiveTasks(QueryFilter filter); //根据filter分页查询活动任务 List<Task> getActiveTasks(Page<Task> page, QueryFilter filter); //根据filter查询流程实例列表 List<Order> getActiveOrders(QueryFilter filter); //根据filter分页查询流程实例列表 List<Order> getActiveOrders(Page<Order> page, QueryFilter filter); //根据filter查询历史流程实例 List<HistoryOrder> getHistoryOrders(QueryFilter filter); //根据filter分页查询历史流程实例 List<HistoryOrder> getHistoryOrders(Page<HistoryOrder> page, QueryFilter filter); //根据filter查询所有已完成的任务 List<HistoryTask> getHistoryTasks(QueryFilter filter); //根据filter分页查询已完成的历史任务 List<HistoryTask> getHistoryTasks(Page<HistoryTask> page, QueryFilter filter); //根据filter分页查询工作项(包含process、order、task三个实体的字段集合) List<WorkItem> getWorkItems(Page<WorkItem> page, QueryFilter filter); //根据filter分页查询抄送工作项(包含process、order) List<HistoryOrder> getCCWorks(Page<HistoryOrder> page, QueryFilter filter); //根据filter分页查询已完成的历史任务项 List<WorkItem> getHistoryWorkItems(Page<WorkItem> page, QueryFilter filter); //根据类型T、Sql语句、参数查询单个对象 public <T> T nativeQueryObject(Class<T> T, String sql, Object... args); //根据类型T、Sql语句、参数查询列表对象 public <T> List<T> nativeQueryList(Class<T> T, String sql, Object... args); //根据类型T、Sql语句、参数分页查询列表对象 public <T> List<T> nativeQueryList(Page<T> page, Class<T> T, String sql, Object... args); 

相关阅读:
Snaker工作流学习(一)
Snaker工作流学习(二)

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/121077.html

(0)
上一篇 2025-10-25 18:45
下一篇 2025-10-25 19:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信