Flowable 脚本 API 深度详解

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 APIfetch() 或 JDBC 连接
错误处理BpmnError()throw new BpmnError('PAYMENT_FAILED')
性能优化缓存APIcache.get('key') / cache.put('key', value)
脚本执行
操作类型
流程控制
变量操作
服务调用
外部集成
execution.signal
execution.terminate
setVariable
getVariable
RuntimeService
TaskService
HTTP/REST
JDBC/SQL

掌握这些 API 便能够:

  • 构建高度动态的业务流程
  • 实现复杂系统集成
  • 创建自适应流程逻辑
  • 开发高效可靠的流程应用
  • 确保企业级安全与合规性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值