任务 - 基础任务类型
CODE 脚本任务
脚本任务对应的实现类是CodeTask 本身没有任何属性 ,但因为其继承自AbstractTask 所以基类的属性可以直接访问。脚本的任务结果就是执行初始化闭包时的返回结果。
实现类
// 脚本任务的实现类
public class CodeTask extends AbstractTask implements Self {
public CodeTask() {
super("CODE", null);
}
}声明示例
// 执行任意groovy脚本代码
t1= CODE {
"hello" // 返回结果,可返回空
}使用建议
- 虽然
CODE任务可以编写任何代码,但应该优先采用现有任务实现,如果现有任务无法满足再采用CODE实现,这样中间过程就是可控的。 - 尽量避免在
CODE中编写过于复杂的任务,一些通用复杂逻辑可考虑封装在某个app应用中。 - 对于复杂的代码要多使用vars做为中间变量,这样出现问题时方便排查。
- 要确保
CODE任务的返回结果是可序列化的,这样流程返回时不会出错。
BOOLE 判断任务
BOOLE任务通常用于处理条件分支,根据返回的true或false决定进入哪条分支,BOOLE任务块中可执行任意代码但其必须返回布尔类型,不能返回空值或其他类型,布尔任务一般通过 when指令来判断执行。
BOOLE判断任务对应的实现类是BooleTask 本身没有任何属性 ,但因为其继承自AbstractTask 所以其基类的属性可以直接访问。
声明示例
// 条件判断任务
t1= BOOLE {
// 可执行任意groovy脚本代码
true // 必须返回布尔类型,不能返回空
}注意事项
- 除返回结果限制外
BOOLE任务与CODE其它特性与行为是一至的,所以CODE任务的建议在BOOLE中同样生效。
CASE 多状态任务
CASE多状态任务用于定义一组状态,该任务会计算当前所处状态,然后when指令会根据其状态值进入对应的分支。
声明语法
// 0.状态A 1.状态B 2.状态C
任务名 = CASE {
状态A = 布尔表达示 // index 0
状态B = 布尔表达示 // index 1
状态C = true // index 2
//..
}- 状态名称可由用户自行定义,只要符groovy命名规范即可,可以是中文但不能与隐式变量、任务基础属性冲突。
- 状态值必须是布尔值,用于确定是否处于当前状态。
- 如果有多个状态同时满足,会根据定义的先后顺序来确认。
- 至少要有一个状态被满足,否则会报错。
CASE任务的结果是一个状态对应的index坐标,该坐标从0开始。when指令会根据index值选择进入对应流程分支。
实现类
CASE 任务的实现类是CaseTask其之所以可以自定义状态名是基于groovy的propertyMissing拦截机制实现,最终所有状态都保存到了CaseTask#items属性中对应代码如下:
java
@Setter
@Getter
public class CaseTask extends AbstractTask {
public CaseTask() {
super("CASE", null);
}
Map<String, Boolean> items = new LinkedHashMap<>(); // 状态存储
}声明示例
//0.已锁定 1.拉黑 2.正常
帐户状态 = CASE {
已锁定 = user.isLock
拉黑 = blacklist.contains(user.id)
正常 = true
}上列中如果已锁定、拉黑两个状态都不满足就会返回第正常状态的索引2。
使用规范与建议
- 如果状态名称很复杂可以通过
items['状态名'] = true方式来定义。 - 状态任务块中除了定义状态也可以写其它代码来计算状态,但要尽量避免使用过于复杂的代码
- 复杂状态计算时可以利用
vars中间变量观察计算过程 - 建议最后定义一个直接为
true的状态,避免所有状态都不成立时出错。
Invoke 调用型任务
调用型任务指调用当前进程之外的服务或资源如HttpTask、SqlTask分别要与http服务以及数据库交互。由于外部服务的不确定性这类任务需要重试、异步处理、调用拦截等机制。所以在ApiFlow中创建了InvokeTask 抽像类它是所有调用型任务的基类,提供了重试、异步处理、调用拦截等机制,这些机制以方法的形式在任务块中进行配置。
InvokeTask 关键代码
public abstract class InvokeTask extends AbstractTask {
/**
* 失败重试,失败判别基于invoke方法执行时任何异常。
* 当某些状态结果为失败时子任务需在invoke实现类中进行判断并throw异常,如http任务中的状态码不等于200。
* @param count 重试次数
* @param interval 重试间隔毫秒数
*/
public void retry(int count, int interval) { }
/**
* 执行失败勿略策略
* @param returnValue 失败时任务的结果,如果该值是一个闭包将返回执行后的结果
*/
public void useIgnore(Object returnValue) { }
/**
* 执行失败中断策略
* @param returnValue 失败时为整个流程返回一个结果,如果该值是一个闭包将返回执行后的结果
*/
public void useAbort(Object returnValue) { }
/**
* 添加任务执行前监听,在任务初始化之后以及任务执行前触发
* @param closure 任务执行的闭包
*/
public void doFirst(Closure<?> closure) {
closure.setDelegate(this);
closure.setResolveStrategy(Closure.DELEGATE_FIRST);
}
/**
* 添加结束监听 ,
* 在任务执行结束后且未出现异常情况下调用。
* 可用于验证结果、转换封装结果以及修改任务状态
*
* @param closure 任务执行的闭包
*/
public void doLast(Closure<?> closure) {
closure.setDelegate(this);
closure.setResolveStrategy(Closure.DELEGATE_FIRST);
}
}配置方法说明
以下是调用型任务支持的配置方法:
retry失败重试 参数分别是重试次数与重试间隔毫秒数useIgnore执行失败勿略策略useAbort执行失败中断策略doFirst添加任务执行前监听,在任务初始化之后以及任务执行前触发。可调用多次。doLast添加结束监听,在任务执行结束后且未出现异常情况下调用。 可用于验证结果、转换封装结果以及修改任务状态等。可调用多次。
HTTP 任务调用配置示例
groovy
t1 = HTTP {
url="https://qqlykm.cn/api/plateNumber/index"
retry 3,2000 // 失败重试3次 每次间隔2000毫秒
useAbort {// 失败时中断整个流程 并返回相应错误码和错误消息。
[errorCode:"0001", errorMsg:_runtimeError.message]
}
doFirst {// 前置调用
cookies["jwt_token"]="xxxxxx" //任务执行前统一添加一个cookie
}
doLast {//后置调用
result = result.data // 任务执行后简化参数。
}
}注意事项
InvokeTask是一个抽象类不可以直接声明。doFirst与doLast可调用多次且每个都会生效retry、useAbort、useIgnore调用多次后只有最后一次的会生效。