Flowable 脚本 API 深度详解
Flowable 的脚本 API 提供了在流程执行过程中动态操作流程状态的能力,是流程自动化与业务集成的核心工具。本文将全面解析脚本 API 的技术细节和使用模式。
一、脚本执行上下文对象
1. Execution 对象 - 流程执行核心控制器
// 获取流程实例ID
const processInstanceId = execution.getProcessInstanceId();
// 获取当前活动ID
const currentActivityId = execution.getCurrentActivityId();
// 获取根流程实例ID
const rootProcessInstanceId = execution.getRootProcessInstanceId();
// 获取上级执行实例
const parentExecution = execution.getParent();
// 触发信号事件
execution.signalEventReceived('emergencyStop');
// 强制终止流程
execution.terminate();
2. DelegateTask 对象 - 任务操作接口
// 设置任务处理人
task.setAssignee('kermit');
// 添加候选组
task.addCandidateGroup('sales-team');
// 设置截止时间
task.setDueDate(new Date(2023, 11, 31));
// 设置优先级(0-100)
task.setPriority(75);
// 完成任务并传递变量
task.complete({ approved: true });
二、变量操作 API
1. 基础变量操作
// 设置流程变量
execution.setVariable('orderTotal', 1499.99);
// 设置局部变量(仅当前作用域)
execution.setVariableLocal('tempCalculation', 42);
// 获取变量
const discountRate = execution.getVariable('discount');
// 获取所有变量
const allVars = execution.getVariables();
// 删除变量
execution.removeVariable('obsoleteData');
2. 变量类型处理
// 设置JSON对象
execution.setVariable(
'userProfile',
{
name: 'Kermit',
roles: ['admin', 'reviewer']
},
'json' // 明确指定类型
);
// 获取JSON对象
const profile = execution.getVariable('userProfile', 'json');
// 设置日期类型
execution.setVariable(
'deliveryDate',
new Date(2023, 11, 25),
'date'
);
// 获取序列化对象(需实现Serializable)
const report = execution.getVariable('monthlyReport', 'serializable');
三、引擎服务 API
1. 运行时服务(RuntimeService)
const runtimeService = execution.getEngineServices().getRuntimeService();
// 启动新流程实例
const newInstance = runtimeService.createProcessInstanceBuilder()
.processDefinitionKey("invoiceApproval")
.variable("amount", 5000)
.start();
// 触发消息事件
runtimeService.messageEventReceived(
"paymentReceived",
execution.getId()
);
// 修改运行中流程
runtimeService.createProcessInstanceModification(processInstanceId)
.cancelActivityInstance("task1")
.startBeforeActivity("reviewTask")
.setVariable("urgent", true)
.execute();
2. 任务服务(TaskService)
const taskService = execution.getEngineServices().getTaskService();
// 查询用户任务
const tasks = taskService.createTaskQuery()
.taskAssignee("kermit")
.processDefinitionKey("expenseReport")
.list();
// 创建独立任务
const adhocTask = taskService.createTask();
adhocTask.setName("Manual Verification");
taskService.saveTask(adhocTask);
// 委托任务
taskService.delegateTask(taskId, "msPiggy");
// 添加任务附件
taskService.createAttachment(
"contract",
taskId,
processInstanceId,
"Contract.pdf",
"Signed contract",
"https://docs/contract123.pdf"
);
3. 身份服务(IdentityService)
const identityService = execution.getEngineServices().getIdentityService();
// 查询用户信息
const user = identityService.createUserQuery()
.userId("kermit")
.singleResult();
// 创建新用户
const newUser = identityService.newUser("fozzie");
newUser.setFirstName("Fozzie");
newUser.setLastName("Bear");
identityService.saveUser(newUser);
// 添加用户到组
identityService.createMembership("fozzie", "actors");
// 验证用户凭据
const valid = identityService.checkPassword("kermit", "frog123");
四、历史服务(HistoryService)
const historyService = execution.getEngineServices().getHistoryService();
// 查询历史流程实例
const historicProcess = historyService.createHistoricProcessInstanceQuery()
.finished()
.variableValueEquals("status", "APPROVED")
.singleResult();
// 获取活动历史
const activities = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId)
.activityType("userTask")
.list();
// 查询变量历史
const varHistory = historyService.createHistoricVariableInstanceQuery()
.variableName("riskLevel")
.orderByTime()
.asc()
.list();
五、表单服务(FormService)
const formService = execution.getEngineServices().getFormService();
// 获取启动表单数据
const startForm = formService.getStartFormData(processDefinitionId);
// 提交启动表单
formService.submitStartFormData(processDefinitionId, {
applicant: "kermit",
amount: 5000
});
// 获取任务表单
const taskForm = formService.getTaskFormData(taskId);
// 提交任务表单
formService.submitTaskFormData(taskId, {
approved: true,
comment: "Within policy limits"
});
六、脚本高级特性
1. 异步脚本执行
<scriptTask id="heavyProcessing"
scriptFormat="javascript"
flowable:async="true"
flowable:exclusive="true">
<script><![CDATA[
// 执行耗时操作(大数据处理)
const result = processBigData(execution.getVariable('dataset'));
execution.setVariable('analysisResult', result);
]]></script>
</scriptTask>
2. 事务控制
try {
// 开始事务
const transaction = execution.getEngineServices()
.getManagementService()
.startTransaction();
// 执行数据库操作
updateInventory(execution.getVariable('order'));
// 提交事务
transaction.commit();
} catch (e) {
// 回滚事务
if(transaction) transaction.rollback();
// 抛出BPMN错误
throw new org.flowable.engine.delegate.BpmnError(
"INVENTORY_ERROR",
"库存更新失败: " + e.message
);
}
3. 外部服务集成
// HTTP REST调用
const response = fetch("https://api.payment.com/process", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
amount: execution.getVariable('amount'),
reference: execution.getProcessInstanceId()
})
});
if (!response.ok) {
throw new Error(`支付失败: ${response.status}`);
}
// 解析响应
const result = response.json();
execution.setVariable('transactionId', result.id);
// JDBC数据库访问
const conn = execution.getEngineServices()
.getProcessEngineConfiguration()
.getDataSource()
.getConnection();
try {
const stmt = conn.prepareStatement(
"UPDATE orders SET status=? WHERE id=?"
);
stmt.setString(1, "PAID");
stmt.setString(2, execution.getVariable('orderId'));
stmt.executeUpdate();
} finally {
conn.close();
}
七、调试与错误处理
1. 日志记录
// 获取Logger
const logger = org.slf4j.LoggerFactory.getLogger("custom.script");
// 记录不同级别日志
logger.debug("Processing order: {}", orderId);
logger.info("Discount applied: {}%", discountRate);
logger.warn("Unusual activity detected: {}", activityId);
logger.error("Payment failed: {}", errorMsg);
// 在历史中记录审计轨迹
execution.setVariableLocal(
"auditTrail",
"Script completed at " + new Date()
);
2. 异常处理
try {
riskyOperation();
} catch (e) {
// 设置错误变量
execution.setVariable('errorCode', 'PROCESS_FAILURE');
// 记录错误详情
logger.error("Script execution failed", e);
// 创建人工干预任务
taskService.createTask()
.setName("Error Intervention: " + execution.getCurrentActivityName())
.setDescription("Error: " + e.message)
.setAssignee("admin")
.save();
// 抛出Flowable异常
throw new org.flowable.engine.delegate.FlowableException(
"SCRIPT_FAILURE",
e
);
}
八、性能优化 API
1. 批量操作
// 批量设置变量
execution.setVariables({
stage: "PROCESSING",
startTime: new Date(),
processor: "auto-system"
});
// 批量创建任务
const taskService = execution.getEngineServices().getTaskService();
const tasks = [];
for (let i = 0; i < 100; i++) {
const task = taskService.newTask();
task.setName(`Verification ${i}`);
tasks.push(task);
}
taskService.bulkSaveTasks(tasks);
2. 缓存利用
// 获取流程引擎缓存
const cache = execution.getEngineServices()
.getProcessEngineConfiguration()
.getCache("scriptCache");
// 缓存计算结果
const cacheKey = `calc_${execution.getVariable('orderId')}`;
let result = cache.get(cacheKey);
if (!result) {
result = heavyCalculation();
cache.put(cacheKey, result, 300); // 缓存5分钟
}
execution.setVariable('result', result);
九、安全 API
1. 权限检查
// 检查用户权限
const canApprove = execution.getEngineServices()
.getIdentityService()
.createPrivilegeQuery()
.userId(task.getAssignee())
.privilegeName("APPROVE_EXPENSE")
.count() > 0;
if (!canApprove) {
throw new Error(
`用户 ${task.getAssignee()} 无审批权限`
);
}
// 数据脱敏
const sensitiveData = execution.getVariable('creditCard');
const maskedData = maskSensitiveInfo(sensitiveData);
execution.setVariableLocal('maskedCard', maskedData);
2. 脚本签名验证
// 验证脚本完整性
const expectedHash = "9f86d081884c7d659a2feaa0c55ad015";
const actualHash = hashScript(scriptContent);
if (expectedHash !== actualHash) {
throw new org.flowable.engine.ScriptValidationException(
"脚本哈希不匹配"
);
}
十、企业级扩展模式
1. Spring 集成
// 获取Spring应用上下文
const appCtx = execution.getEngineServices()
.getProcessEngineConfiguration()
.getApplicationContext();
// 调用Spring Bean
const paymentService = appCtx.getBean("paymentService");
const result = paymentService.process(
execution.getVariable('paymentRequest')
);
execution.setVariable('paymentStatus', result.status);
2. 自定义脚本函数
// 注册自定义函数
public class CustomScriptFunctions {
public static String formatCurrency(Double amount) {
return NumberFormat.getCurrencyInstance().format(amount);
}
}
// 在脚本中使用
const total = execution.getVariable('orderTotal');
const formatted = formatCurrency(total);
execution.setVariable('displayTotal', formatted);
最佳实践总结
场景 | 推荐API | 示例 |
---|---|---|
流程控制 | Execution.signal() | execution.signalEventReceived('continue') |
任务操作 | TaskService.complete() | taskService.complete(taskId, variables) |
批量处理 | BulkSaveTasks() | taskService.bulkSaveTasks(taskList) |
外部集成 | REST/DB API | fetch() 或 JDBC 连接 |
错误处理 | BpmnError() | throw new BpmnError('PAYMENT_FAILED') |
性能优化 | 缓存API | cache.get('key') / cache.put('key', value) |
掌握这些 API 便能够:
- 构建高度动态的业务流程
- 实现复杂系统集成
- 创建自适应流程逻辑
- 开发高效可靠的流程应用
- 确保企业级安全与合规性