工具类API
概述
ApiFlow 在工作流中自动导入了一些常用的工具类,这些工具类提供了静态方法,可以在工作流的任何地方直接调用,无需额外导入。本章节介绍这些工具类的使用方法。
自动导入的工具类
ApiFlow 默认导入以下工具类:
JSON- JSON 序列化与反序列化工具Assert- 断言验证工具
这些工具类可以在工作流的任意位置直接使用其静态方法,包括任务定义、编排指令中等。
JSON 工具类
JSON 工具类提供了 JSON 数据的序列化和反序列化功能,基于 Jackson 库实现。
JSON.parse() - 解析JSON
将 JSON 字符串解析为 Java 对象。
JSON.parse(jsonString)参数:
jsonString(String) - JSON 格式的字符串
返回值:
Object- 解析后的对象,可能是 Map、List、String、Number、Boolean 等类型
示例:
// 解析JSON对象
task1 = CODE {
def jsonStr = '{"name":"张三","age":25,"city":"北京"}'
def obj = JSON.parse(jsonStr)
return obj.name // 返回 "张三"
}
// 解析JSON数组
task2 = CODE {
def jsonStr = '[{"id":1,"name":"产品A"},{"id":2,"name":"产品B"}]'
def list = JSON.parse(jsonStr)
return list[0].name // 返回 "产品A"
}
// 在HTTP任务中使用
httpTask = HTTP {
url = "https://api.example.com/data"
method = "GET"
}
parseTask = CODE {
// 假设httpTask返回JSON字符串
def data = JSON.parse(httpTask.result)
return data.items.size()
}
start {
run httpTask
run parseTask
}JSON.string() - 序列化为JSON
将 Java 对象序列化为 JSON 字符串。
JSON.string(object)参数:
object(Object) - 要序列化的对象(Map、List、POJO等)
返回值:
String- JSON 格式的字符串
示例:
// 将Map转为JSON
task1 = CODE {
def data = [
name: "李四",
age: 30,
hobbies: ["阅读", "旅游", "编程"]
]
return JSON.string(data)
// 返回: {"name":"李四","age":30,"hobbies":["阅读","旅游","编程"]}
}
// 在HTTP请求中使用
prepareData = CODE {
return [
username: "admin",
password: "123456",
remember: true
]
}
loginTask = HTTP {
url = "https://api.example.com/login"
method = "POST"
contentType = "application/json"
body = ${-> JSON.string(prepareData.result)}
}
start {
run prepareData
run loginTask
}
// 列表转JSON
task2 = CODE {
def users = [
[id: 1, name: "用户A"],
[id: 2, name: "用户B"],
[id: 3, name: "用户C"]
]
return JSON.string(users)
}JSON 使用场景
HTTP 请求/响应处理
groovy// 发送JSON请求 task1 = HTTP { url = "https://api.example.com/create" method = "POST" contentType = "application/json" body = ${-> JSON.string([name: "新项目", status: "active"])} } // 解析JSON响应 task2 = CODE { def response = JSON.parse(task1.result) return response.id }数据转换
groovy// 将数据库查询结果转为JSON dbTask = mysql "SELECT * FROM users WHERE status = 'active'" convertTask = CODE { return JSON.string(dbTask.result) }日志记录
groovytask1 = CODE { def logData = [ timestamp: new Date(), action: "user_login", userId: input.userId ] log.info("操作日志: {}", JSON.string(logData)) return true }
JSON 注意事项
JSON.parse()解析失败时会抛出RuntimeExceptionJSON.string()序列化时会忽略null值的字段- 支持 Groovy 的
GString类型自动转换 - 不支持循环引用的对象序列化
Assert 工具类
Assert 工具类提供了参数验证和断言功能,用于在工作流执行过程中验证数据的有效性。断言失败时会抛出 IllegalArgumentException 或 IllegalStateException。
Assert.notNull() - 非空断言
断言对象不为 null。
Assert.notNull(object)
Assert.notNull(object, message)参数:
object(Object) - 待检查的对象message(String, 可选) - 断言失败时的错误消息
示例:
task1 = CODE {
def userId = input.userId
Assert.notNull(userId, "用户ID不能为空")
return userId
}
// 检查任务结果
task2 = CODE {
def result = task1.result
Assert.notNull(result) // 使用默认错误消息
return result
}Assert.isNull() - 空值断言
断言对象为 null。
Assert.isNull(object)
Assert.isNull(object, message)示例:
task1 = CODE {
def cache = input.cache
Assert.isNull(cache, "缓存应该为空")
// 初始化逻辑...
}Assert.isTrue() - 布尔真值断言
断言表达式为 true。
Assert.isTrue(expression)
Assert.isTrue(expression, message)示例:
task1 = CODE {
def age = input.age
Assert.isTrue(age >= 18, "年龄必须大于等于18岁")
return age
}
// 验证业务规则
checkTask = CODE {
def amount = input.amount
def balance = input.balance
Assert.isTrue(amount <= balance, "余额不足")
return true
}Assert.isFalse() - 布尔假值断言
断言表达式为 false。
Assert.isFalse(expression)
Assert.isFalse(expression, message)示例:
task1 = CODE {
def isLocked = input.accountLocked
Assert.isFalse(isLocked, "账户已锁定,无法操作")
return true
}Assert.hasText() - 文本非空断言
断言字符串不为 null、不为空字符串、且包含至少一个非空白字符。
Assert.hasText(text)
Assert.hasText(text, message)示例:
task1 = CODE {
def username = input.username
Assert.hasText(username, "用户名不能为空")
def password = input.password
Assert.hasText(password, "密码不能为空")
return [username: username, password: password]
}Assert.hasLength() - 字符串长度断言
断言字符串不为 null 且长度大于 0。
Assert.hasLength(text)
Assert.hasLength(text, message)示例:
task1 = CODE {
def code = input.verifyCode
Assert.hasLength(code, "验证码不能为空")
return code
}Assert.state() - 状态断言
断言状态表达式为 true,失败时抛出 IllegalStateException(而非 IllegalArgumentException)。
Assert.state(expression)
Assert.state(expression, message)示例:
task1 = CODE {
def status = input.orderStatus
Assert.state(status == "pending", "订单状态必须为pending才能修改")
// 执行修改逻辑...
}Assert.isInstanceOf() - 类型断言
断言对象是指定类的实例。
Assert.isInstanceOf(clazz, object)
Assert.isInstanceOf(clazz, object, message)示例:
task1 = CODE {
def data = input.data
Assert.isInstanceOf(Map.class, data, "数据必须是Map类型")
return data.name
}Assert.noNullElements() - 数组无空元素断言
断言数组中没有 null 元素。
Assert.noNullElements(array)
Assert.noNullElements(array, message)示例:
task1 = CODE {
def items = input.items as Object[]
Assert.noNullElements(items, "列表中不能包含空元素")
return items.length
}Assert.notEmpty() - 集合非空断言
断言集合不为空。
Assert.notEmpty(collection, message)示例:
task1 = CODE {
def userList = input.users
Assert.notEmpty(userList, "用户列表不能为空")
return userList.size()
}Assert 使用场景
输入参数验证
groovyvalidateInput = CODE { Assert.notNull(input.orderId, "订单ID不能为空") Assert.hasText(input.productName, "产品名称不能为空") Assert.isTrue(input.quantity > 0, "数量必须大于0") Assert.isTrue(input.price >= 0, "价格不能为负数") return true } start { run validateInput // 后续处理... }业务规则校验
groovycheckOrder = CODE { def stock = input.stock def quantity = input.quantity Assert.isTrue(quantity <= stock, "库存不足,当前库存:${stock}") return true }前置条件检查
groovycheckPermission = CODE { def role = input.userRole Assert.isTrue(role in ["admin", "manager"], "权限不足,需要管理员权限") return true } start { run checkPermission // 执行需要权限的操作... }任务结果验证
groovyhttpTask = HTTP { url = "https://api.example.com/data" } validateResult = CODE { def result = httpTask.result Assert.notNull(result, "API返回结果为空") def data = JSON.parse(result) Assert.isTrue(data.code == 200, "API返回错误: ${data.message}") return data.data } start { run httpTask run validateResult }
Assert 注意事项
- 断言失败会立即中断流程并抛出异常
- 大部分方法抛出
IllegalArgumentException,Assert.state()抛出IllegalStateException - 建议在工作流开始时进行输入验证,避免执行到一半才发现参数错误
- 合理使用断言可以提高代码的健壮性和可维护性
Groovy 默认导入
除了 ApiFlow 提供的工具类外,Groovy 还默认导入了以下包和类,可以在工作流中直接使用:
默认导入的包
import java.lang.*
import java.util.*
import java.io.*
import java.net.*
import groovy.lang.*
import groovy.util.*
import java.math.BigInteger
import java.math.BigDecimal常用类示例
// 日期类(java.util.Date)
task1 = CODE {
def now = new Date()
log.info("当前时间: {}", now)
return now
}
// 集合类(java.util.List, Map, Set)
task2 = CODE {
def list = new ArrayList()
list.add("item1")
list.add("item2")
def map = new HashMap()
map.put("key1", "value1")
return [list: list, map: map]
}
// 文件操作(java.io.File)
task3 = CODE {
def file = new File("/tmp/test.txt")
return file.exists()
}
// URL操作(java.net.URL)
task4 = CODE {
def url = new URL("https://example.com")
return url.protocol // 返回 "https"
}
// 大数运算(java.math.BigDecimal)
task5 = CODE {
def price = new BigDecimal("99.99")
def quantity = new BigDecimal("3")
return price.multiply(quantity) // 精确计算 299.97
}Groovy 特有功能
Groovy 提供了许多语法糖和增强功能:
// 字符串增强
task1 = CODE {
def str = "hello"
return str.capitalize() // "Hello"
}
// 集合操作
task2 = CODE {
def list = [1, 2, 3, 4, 5]
def result = list.findAll { it > 2 } // [3, 4, 5]
return result
}
// 范围(Range)
task3 = CODE {
def range = 1..10
return range.collect { it * 2 } // [2, 4, 6, ..., 20]
}
// Elvis 操作符
task4 = CODE {
def value = input.name ?: "默认名称"
return value
}
// 安全导航操作符
task5 = CODE {
def name = input?.user?.name // 自动处理null
return name
}综合示例
以下是一个综合使用 JSON 和 Assert 工具类的完整示例:
// 验证输入参数
validateInput = CODE {
Assert.notNull(input.userId, "用户ID不能为空")
Assert.hasText(input.action, "操作类型不能为空")
return true
}
// 查询用户信息
getUserInfo = HTTP {
url = "https://api.example.com/users/${-> input.userId}"
method = "GET"
}
// 解析并验证用户信息
parseUserInfo = CODE {
def userJson = getUserInfo.result
def user = JSON.parse(userJson)
Assert.notNull(user, "用户信息获取失败")
Assert.hasText(user.name, "用户名称为空")
Assert.isFalse(user.locked, "用户已被锁定")
return user
}
// 构建操作日志
buildLog = CODE {
def logData = [
userId: input.userId,
userName: parseUserInfo.result.name,
action: input.action,
timestamp: new Date().time,
ip: input.clientIp
]
return JSON.string(logData)
}
// 保存日志
saveLog = HTTP {
url = "https://api.example.com/logs"
method = "POST"
contentType = "application/json"
body = ${-> buildLog.result}
}
start {
run validateInput
run getUserInfo
run parseUserInfo
run buildLog
run saveLog
}最佳实践
输入验证优先
- 在工作流开始时立即验证所有输入参数
- 使用 Assert 进行参数校验,快速失败
JSON处理规范
- 使用
JSON.parse()解析外部API返回的JSON字符串 - 使用
JSON.string()序列化要发送的请求体 - 捕获并处理可能的解析异常
- 使用
错误消息清晰
- Assert 断言时提供清晰的错误消息
- 包含必要的上下文信息,便于问题排查
合理使用Groovy特性
- 利用Groovy的语法糖简化代码
- 使用安全导航操作符避免空指针异常
- 使用集合操作方法提高代码可读性