🎯 目标: 设计可扩展的步骤执行器架构,实现各种类型的步骤执行逻辑
🤔 为什么需要多种执行器?
不同的业务场景需要不同的执行逻辑:
- 🔀 条件分支: 根据条件选择不同的执行路径
- ⚡ 并行执行: 同时执行多个独立的任务
- 🔄 循环执行: 重复执行某些步骤直到满足条件
- 📝 脚本执行: 动态执行脚本代码
- 🌐 远程调用: 调用外部服务或API
🏗️ 执行器架构设计
graph TB
subgraph "StepExecutor 接口层 🎯"
A1[StepExecutor]
A2[AbstractStepExecutor]
end
subgraph "基础执行器 🔧"
B1[SimpleStepExecutor]
B2[ServiceStepExecutor]
B3[ScriptStepExecutor]
end
subgraph "控制流执行器 🔀"
C1[ConditionalStepExecutor]
C2[ParallelStepExecutor]
C3[LoopStepExecutor]
C4[ScriptConditionalStepExecutor]
end
subgraph "扩展执行器 🚀"
D1[HttpStepExecutor]
D2[DatabaseStepExecutor]
D3[MessageStepExecutor]
end
A1 --> A2
A2 --> B1
A2 --> B2
A2 --> B3
A2 --> C1
A2 --> C2
A2 --> C3
A2 --> C4
A2 --> D1
A2 --> D2
A2 --> D3
🎯 AbstractStepExecutor基类
java
/**
* 步骤执行器抽象基类
* 提供通用的执行逻辑和模板方法
*/
public abstract class AbstractStepExecutor implements StepExecutor {
protected static final Logger logger = LoggerFactory.getLogger(AbstractStepExecutor.class);
@Override
public final StepExecutionResult execute(StepDefinition stepDefinition, FlowContext context) {
long startTime = System.currentTimeMillis();
String stepId = stepDefinition.getId();
logger.debug("开始执行步骤: {} [{}]", stepDefinition.getName(), stepId);
try {
// 前置处理
preExecute(stepDefinition, context);
// 执行核心逻辑
Object result = doExecute(stepDefinition, context);
// 后置处理
postExecute(stepDefinition, context, result);
long endTime = System.currentTimeMillis();
logger.debug("步骤执行成功: {} [{}], 耗时: {}ms",
stepDefinition.getName(), stepId, endTime - startTime);
return createSuccessResult(stepDefinition, result, startTime, endTime);
} catch (Exception e) {
long endTime = System.currentTimeMillis();
logger.error("步骤执行失败: {} [{}], 耗时: {}ms",
stepDefinition.getName(), stepId, endTime - startTime, e);
return createFailureResult(stepDefinition, e, startTime, endTime);
}
}
/**
* 执行前置处理
* @param stepDefinition 步骤定义
* @param context 执行上下文
*/
protected void preExecute(StepDefinition stepDefinition, FlowContext context) {
// 默认空实现,子类可以重写
}
/**
* 执行核心逻辑(子类必须实现)
* @param stepDefinition 步骤定义
* @param context 执行上下文
* @return 执行结果
*/
protected abstract Object doExecute(StepDefinition stepDefinition, FlowContext context) throws Exception;
/**
* 执行后置处理
* @param stepDefinition 步骤定义
* @param context 执行上下文
* @param result 执行结果
*/
protected void postExecute(StepDefinition stepDefinition, FlowContext context, Object result) {
// 保存结果到上下文
String resultKey = getResultKey(stepDefinition);
if (resultKey != null && result != null) {
context.put(resultKey, result);
}
}
/**
* 获取结果保存的键名
*/
protected String getResultKey(StepDefinition stepDefinition) {
return (String) stepDefinition.getConfig().get("resultKey");
}
/**
* 创建成功结果
*/
protected StepExecutionResult createSuccessResult(
StepDefinition stepDefinition, Object result, long startTime, long endTime) {
return new StepExecutionResult(
stepDefinition.getId(),
stepDefinition.getType(),
FlowExecutionResult.Status.SUCCESS,
result,
startTime,
endTime,
null
);
}
/**
* 创建失败结果
*/
protected StepExecutionResult createFailureResult(
StepDefinition stepDefinition, Exception exception, long startTime, long endTime) {
return new StepExecutionResult(
stepDefinition.getId(),
stepDefinition.getType(),
FlowExecutionResult.Status.FAILED,
null,
startTime,
endTime,
exception
);
}
/**
* 获取配置值
*/
protected <T> T getConfig(StepDefinition stepDefinition, String key, Class<T> type) {
Object value = stepDefinition.getConfig().get(key);
if (value == null) {
return null;
}
if (type.isInstance(value)) {
return type.cast(value);
}
throw new IllegalArgumentException(
String.format("配置 %s 的类型不匹配,期望: %s, 实际: %s",
key, type.getSimpleName(), value.getClass().getSimpleName())
);
}
/**
* 获取必需的配置值
*/
protected <T> T getRequiredConfig(StepDefinition stepDefinition, String key, Class<T> type) {
T value = getConfig(stepDefinition, key, type);
if (value == null) {
throw new IllegalArgumentException(
String.format("步骤 %s 缺少必需的配置: %s", stepDefinition.getId(), key)
);
}
return value;
}
}
🔀 ConditionalStepExecutor - 条件执行器
java
/**
* 条件步骤执行器
* 根据条件表达式选择执行不同的分支
*/
public class ConditionalStepExecutor extends AbstractStepExecutor {
private final ExpressionEvaluator expressionEvaluator;
private final FlowEngine flowEngine;
public ConditionalStepExecutor(ExpressionEvaluator expressionEvaluator, FlowEngine flowEngine) {
this.expressionEvaluator = expressionEvaluator;
this.flowEngine = flowEngine;
}
@Override
protected Object doExecute(StepDefinition stepDefinition, FlowContext context) throws Exception {
// 获取条件表达式
String condition = getRequiredConfig(stepDefinition, "condition", String.class);
// 评估条件
boolean conditionResult = expressionEvaluator.evaluateBoolean(condition, context);
logger.debug("条件评估结果: {} -> {}", condition, conditionResult);
// 根据条件选择执行分支
List<StepDefinition> targetSteps = conditionResult ?
getTrueSteps(stepDefinition) : getFalseSteps(stepDefinition);
if (targetSteps == null || targetSteps.isEmpty()) {
logger.debug("没有找到匹配的执行分支");
return conditionResult;
}
// 执行选中的步骤
List<StepExecutionResult> branchResults = new ArrayList<>();
for (StepDefinition step : targetSteps) {
StepExecutor executor = flowEngine.getExecutor(step.getType());
if (executor == null) {
throw new IllegalStateException("未找到步骤类型的执行器: " + step.getType());
}
StepExecutionResult result = executor.execute(step, context);
branchResults.add(result);
// 如果步骤失败,根据配置决定是否继续
if (result.getStatus() == FlowExecutionResult.Status.FAILED &&
!shouldContinueOnFailure(step)) {
break;
}
}
return new ConditionalExecutionResult(conditionResult, branchResults);
}
/**
* 获取条件为真时执行的步骤
*/
@SuppressWarnings("unchecked")
private List<StepDefinition> getTrueSteps(StepDefinition stepDefinition) {
return (List<StepDefinition>) stepDefinition.getConfig().get("trueSteps");
}
/**
* 获取条件为假时执行的步骤
*/
@SuppressWarnings("unchecked")
private List<StepDefinition> getFalseSteps(StepDefinition stepDefinition) {
return (List<StepDefinition>) stepDefinition.getConfig().get("falseSteps");
}
/**
* 判断失败时是否继续执行
*/
private boolean shouldContinueOnFailure(StepDefinition stepDefinition) {
Boolean continueOnFailure = getConfig(stepDefinition, "continueOnFailure", Boolean.class);
return Boolean.TRUE.equals(continueOnFailure);
}
@Override
public StepType getSupportedType() {
return StepType.CONDITIONAL;
}
@Override
public ValidationResult validate(StepDefinition stepDefinition) {
// 验证条件表达式
String condition = getConfig(stepDefinition, "condition", String.class);
if (condition == null || condition.trim().isEmpty()) {
return ValidationResult.error("条件步骤必须指定condition配置");
}
// 验证至少有一个分支
List<StepDefinition> trueSteps = getTrueSteps(stepDefinition);
List<StepDefinition> falseSteps = getFalseSteps(stepDefinition);
if ((trueSteps == null || trueSteps.isEmpty()) &&
(falseSteps == null || falseSteps.isEmpty())) {
return ValidationResult.error("条件步骤必须至少指定一个执行分支");
}
return ValidationResult.success();
}
/**
* 条件执行结果
*/
public static class ConditionalExecutionResult {
private final boolean conditionResult;
private final List<StepExecutionResult> branchResults;
public ConditionalExecutionResult(boolean conditionResult, List<StepExecutionResult> branchResults) {
this.conditionResult = conditionResult;
this.branchResults = branchResults;
}
// getter方法...
}
}
⚡ ParallelStepExecutor - 并行执行器
java
/**
* 并行步骤执行器
* 同时执行多个独立的步骤
*/
public class ParallelStepExecutor extends AbstractStepExecutor {
private final FlowEngine flowEngine;
private final ExecutorService executorService;
public ParallelStepExecutor(FlowEngine flowEngine) {
this.flowEngine = flowEngine;
this.executorService = Executors.newCachedThreadPool(
new ThreadFactoryBuilder()
.setNameFormat("parallel-step-%d")
.setDaemon(true)
.build()
);
}
@Override
protected Object doExecute(StepDefinition stepDefinition, FlowContext context) throws Exception {
// 获取并行执行的步骤
List<StepDefinition> parallelSteps = getParallelSteps(stepDefinition);
if (parallelSteps == null || parallelSteps.isEmpty()) {
logger.warn("并行步骤没有配置子步骤");
return Collections.emptyList();
}
// 获取超时配置
Integer timeoutSeconds = getConfig(stepDefinition, "timeoutSeconds", Integer.class);
long timeout = timeoutSeconds != null ? timeoutSeconds : 300; // 默认5分钟
logger.debug("开始并行执行 {} 个步骤,超时: {}秒", parallelSteps.size(), timeout);
// 创建并行任务
List<CompletableFuture<StepExecutionResult>> futures = new ArrayList<>();
for (StepDefinition step : parallelSteps) {
CompletableFuture<StepExecutionResult> future = CompletableFuture.supplyAsync(
() -> executeStep(step, context.createChild()),
executorService
);
futures.add(future);
}
// 等待所有任务完成
try {
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
futures.toArray(new CompletableFuture[0])
);
allFutures.get(timeout, TimeUnit.SECONDS);
// 收集结果
List<StepExecutionResult> results = new ArrayList<>();
for (CompletableFuture<StepExecutionResult> future : futures) {
results.add(future.get());
}
logger.debug("并行执行完成,成功: {}, 失败: {}",
countSuccessful(results), countFailed(results));
return new ParallelExecutionResult(results);
} catch (TimeoutException e) {
// 取消未完成的任务
for (CompletableFuture<StepExecutionResult> future : futures) {
future.cancel(true);
}
throw new RuntimeException("并行执行超时: " + timeout + "秒", e);
}
}
/**
* 执行单个步骤
*/
private StepExecutionResult executeStep(StepDefinition stepDefinition, FlowContext context) {
try {
StepExecutor executor = flowEngine.getExecutor(stepDefinition.getType());
if (executor == null) {
throw new IllegalStateException("未找到步骤类型的执行器: " + stepDefinition.getType());
}
return executor.execute(stepDefinition, context);
} catch (Exception e) {
logger.error("并行步骤执行异常: {}", stepDefinition.getId(), e);
return new StepExecutionResult(
stepDefinition.getId(),
stepDefinition.getType(),
FlowExecutionResult.Status.FAILED,
null,
System.currentTimeMillis(),
System.currentTimeMillis(),
e
);
}
}
/**
* 获取并行执行的步骤
*/
@SuppressWarnings("unchecked")
private List<StepDefinition> getParallelSteps(StepDefinition stepDefinition) {
return (List<StepDefinition>) stepDefinition.getConfig().get("steps");
}
/**
* 统计成功的步骤数量
*/
private long countSuccessful(List<StepExecutionResult> results) {
return results.stream()
.filter(r -> r.getStatus() == FlowExecutionResult.Status.SUCCESS)
.count();
}
/**
* 统计失败的步骤数量
*/
private long countFailed(List<StepExecutionResult> results) {
return results.stream()
.filter(r -> r.getStatus() == FlowExecutionResult.Status.FAILED)
.count();
}
@Override
public StepType getSupportedType() {
return StepType.PARALLEL;
}
@Override
public ValidationResult validate(StepDefinition stepDefinition) {
List<StepDefinition> steps = getParallelSteps(stepDefinition);
if (steps == null || steps.isEmpty()) {
return ValidationResult.error("并行步骤必须配置至少一个子步骤");
}
// 验证超时配置
Integer timeoutSeconds = getConfig(stepDefinition, "timeoutSeconds", Integer.class);
if (timeoutSeconds != null && timeoutSeconds <= 0) {
return ValidationResult.error("超时时间必须大于0");
}
return ValidationResult.success();
}
/**
* 关闭执行器
*/
public void shutdown() {
executorService.shutdown();
try {
if (!executorService.awaitTermination(30, TimeUnit.SECONDS)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
Thread.currentThread().interrupt();
}
}
/**
* 并行执行结果
*/
public static class ParallelExecutionResult {
private final List<StepExecutionResult> results;
public ParallelExecutionResult(List<StepExecutionResult> results) {
this.results = results;
}
public List<StepExecutionResult> getResults() {
return results;
}
public boolean hasFailures() {
return results.stream()
.anyMatch(r -> r.getStatus() == FlowExecutionResult.Status.FAILED);
}
public List<StepExecutionResult> getSuccessfulResults() {
return results.stream()
.filter(r -> r.getStatus() == FlowExecutionResult.Status.SUCCESS)
.collect(Collectors.toList());
}
public List<StepExecutionResult> getFailedResults() {
return results.stream()
.filter(r -> r.getStatus() == FlowExecutionResult.Status.FAILED)
.collect(Collectors.toList());
}
}
}
🔄 LoopStepExecutor - 循环执行器
java
/**
* 循环步骤执行器
* 重复执行步骤直到满足退出条件
*/
public class LoopStepExecutor extends AbstractStepExecutor {
private final ExpressionEvaluator expressionEvaluator;
private final FlowEngine flowEngine;
public LoopStepExecutor(ExpressionEvaluator expressionEvaluator, FlowEngine flowEngine) {
this.expressionEvaluator = expressionEvaluator;
this.flowEngine = flowEngine;
}
@Override
protected Object doExecute(StepDefinition stepDefinition, FlowContext context) throws Exception {
// 获取循环配置
String condition = getConfig(stepDefinition, "condition", String.class);
Integer maxIterations = getConfig(stepDefinition, "maxIterations", Integer.class);
List<StepDefinition> loopSteps = getLoopSteps(stepDefinition);
if (loopSteps == null || loopSteps.isEmpty()) {
logger.warn("循环步骤没有配置子步骤");
return Collections.emptyList();
}
// 设置默认值
if (maxIterations == null) {
maxIterations = 100; // 默认最大100次迭代
}
logger.debug("开始循环执行,最大迭代次数: {}, 条件: {}", maxIterations, condition);
List<LoopIterationResult> iterationResults = new ArrayList<>();
int iteration = 0;
while (iteration < maxIterations) {
iteration++;
logger.debug("开始第 {} 次迭代", iteration);
// 设置迭代变量
context.put("_iteration", iteration);
context.put("_isFirstIteration", iteration == 1);
// 执行循环体
List<StepExecutionResult> stepResults = new ArrayList<>();
boolean shouldBreak = false;
for (StepDefinition step : loopSteps) {
StepExecutor executor = flowEngine.getExecutor(step.getType());
if (executor == null) {
throw new IllegalStateException("未找到步骤类型的执行器: " + step.getType());
}
StepExecutionResult result = executor.execute(step, context);
stepResults.add(result);
// 如果步骤失败,根据配置决定是否继续
if (result.getStatus() == FlowExecutionResult.Status.FAILED) {
if (!shouldContinueOnFailure(step)) {
shouldBreak = true;
break;
}
}
}
iterationResults.add(new LoopIterationResult(iteration, stepResults));
// 如果步骤失败需要退出
if (shouldBreak) {
logger.debug("由于步骤失败,退出循环");
break;
}
// 检查退出条件
if (condition != null && !condition.trim().isEmpty()) {
try {
boolean shouldContinue = expressionEvaluator.evaluateBoolean(condition, context);
if (!shouldContinue) {
logger.debug("满足退出条件,结束循环");
break;
}
} catch (Exception e) {
logger.warn("循环条件评估失败: {}", condition, e);
break;
}
}
}
// 清理迭代变量
context.remove("_iteration");
context.remove("_isFirstIteration");
logger.debug("循环执行完成,总迭代次数: {}", iteration);
return new LoopExecutionResult(iteration, iterationResults);
}
/**
* 获取循环执行的步骤
*/
@SuppressWarnings("unchecked")
private List<StepDefinition> getLoopSteps(StepDefinition stepDefinition) {
return (List<StepDefinition>) stepDefinition.getConfig().get("steps");
}
/**
* 判断失败时是否继续执行
*/
private boolean shouldContinueOnFailure(StepDefinition stepDefinition) {
Boolean continueOnFailure = getConfig(stepDefinition, "continueOnFailure", Boolean.class);
return Boolean.TRUE.equals(continueOnFailure);
}
@Override
public StepType getSupportedType() {
return StepType.LOOP;
}
@Override
public ValidationResult validate(StepDefinition stepDefinition) {
List<StepDefinition> steps = getLoopSteps(stepDefinition);
if (steps == null || steps.isEmpty()) {
return ValidationResult.error("循环步骤必须配置至少一个子步骤");
}
// 验证最大迭代次数
Integer maxIterations = getConfig(stepDefinition, "maxIterations", Integer.class);
if (maxIterations != null && maxIterations <= 0) {
return ValidationResult.error("最大迭代次数必须大于0");
}
return ValidationResult.success();
}
/**
* 循环迭代结果
*/
public static class LoopIterationResult {
private final int iteration;
private final List<StepExecutionResult> stepResults;
public LoopIterationResult(int iteration, List<StepExecutionResult> stepResults) {
this.iteration = iteration;
this.stepResults = stepResults;
}
// getter方法...
}
/**
* 循环执行结果
*/
public static class LoopExecutionResult {
private final int totalIterations;
private final List<LoopIterationResult> iterationResults;
public LoopExecutionResult(int totalIterations, List<LoopIterationResult> iterationResults) {
this.totalIterations = totalIterations;
this.iterationResults = iterationResults;
}
// getter方法...
}
}
📝 ScriptStepExecutor - 脚本执行器
java
/**
* 脚本步骤执行器
* 执行动态脚本代码
*/
public class ScriptStepExecutor extends AbstractStepExecutor {
private final Map<String, ScriptEngine> scriptEngines = new ConcurrentHashMap<>();
public ScriptStepExecutor() {
initializeScriptEngines();
}
@Override
protected Object doExecute(StepDefinition stepDefinition, FlowContext context) throws Exception {
// 获取脚本配置
String scriptType = getRequiredConfig(stepDefinition, "scriptType", String.class);
String script = getRequiredConfig(stepDefinition, "script", String.class);
logger.debug("执行脚本: 类型={}, 长度={}", scriptType, script.length());
// 获取脚本引擎
ScriptEngine engine = getScriptEngine(scriptType);
if (engine == null) {
throw new IllegalArgumentException("不支持的脚本类型: " + scriptType);
}
// 设置脚本上下文
setupScriptContext(engine, context);
// 执行脚本
Object result = engine.eval(script);
logger.debug("脚本执行完成,结果类型: {}",
result != null ? result.getClass().getSimpleName() : "null");
return result;
}
/**
* 初始化脚本引擎
*/
private void initializeScriptEngines() {
ScriptEngineManager manager = new ScriptEngineManager();
// JavaScript引擎
ScriptEngine jsEngine = manager.getEngineByName("javascript");
if (jsEngine != null) {
scriptEngines.put("javascript", jsEngine);
scriptEngines.put("js", jsEngine);
}
// Groovy引擎(如果可用)
ScriptEngine groovyEngine = manager.getEngineByName("groovy");
if (groovyEngine != null) {
scriptEngines.put("groovy", groovyEngine);
}
// Kotlin引擎(如果可用)
ScriptEngine kotlinEngine = manager.getEngineByName("kotlin");
if (kotlinEngine != null) {
scriptEngines.put("kotlin", kotlinEngine);
scriptEngines.put("kts", kotlinEngine);
}
logger.info("已初始化脚本引擎: {}", scriptEngines.keySet());
}
/**
* 获取脚本引擎
*/
private ScriptEngine getScriptEngine(String scriptType) {
return scriptEngines.get(scriptType.toLowerCase());
}
/**
* 设置脚本上下文
*/
private void setupScriptContext(ScriptEngine engine, FlowContext context) {
Bindings bindings = engine.createBindings();
// 添加上下文数据
bindings.put("context", context);
// 添加所有上下文变量
for (Map.Entry<String, Object> entry : context.getAll().entrySet()) {
bindings.put(entry.getKey(), entry.getValue());
}
// 添加工具函数
bindings.put("logger", logger);
bindings.put("System", System.class);
bindings.put("Math", Math.class);
engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
}
@Override
public StepType getSupportedType() {
return StepType.SCRIPT;
}
@Override
public ValidationResult validate(StepDefinition stepDefinition) {
String scriptType = getConfig(stepDefinition, "scriptType", String.class);
if (scriptType == null || scriptType.trim().isEmpty()) {
return ValidationResult.error("脚本步骤必须指定scriptType配置");
}
String script = getConfig(stepDefinition, "script", String.class);
if (script == null || script.trim().isEmpty()) {
return ValidationResult.error("脚本步骤必须指定script配置");
}
// 检查脚本引擎是否可用
if (getScriptEngine(scriptType) == null) {
return ValidationResult.error("不支持的脚本类型: " + scriptType +
", 可用类型: " + scriptEngines.keySet());
}
return ValidationResult.success();
}
}
🧪 执行器测试示例
java
public class StepExecutorTest {
private FlowEngine flowEngine;
private FlowContext context;
@Before
public void setUp() {
flowEngine = new DefaultFlowEngine();
context = new DefaultFlowContext();
// 注册执行器
flowEngine.registerExecutor(StepType.CONDITIONAL,
new ConditionalStepExecutor(new SimpleExpressionEvaluator(), flowEngine));
flowEngine.registerExecutor(StepType.PARALLEL,
new ParallelStepExecutor(flowEngine));
flowEngine.registerExecutor(StepType.LOOP,
new LoopStepExecutor(new SimpleExpressionEvaluator(), flowEngine));
flowEngine.registerExecutor(StepType.SCRIPT,
new ScriptStepExecutor());
}
@Test
public void testConditionalExecutor() {
// 创建条件步骤
StepDefinition conditionalStep = StepDefinitionBuilder
.builder("age-check", StepType.CONDITIONAL)
.config("condition", "context.get('age') >= 18")
.config("trueSteps", Arrays.asList(
StepDefinitionBuilder
.builder("adult-process", StepType.SIMPLE)
.config("action", "set")
.config("value", "成年人处理")
.config("targetKey", "result")
.build()
))
.config("falseSteps", Arrays.asList(
StepDefinitionBuilder
.builder("minor-process", StepType.SIMPLE)
.config("action", "set")
.config("value", "未成年人处理")
.config("targetKey", "result")
.build()
))
.build();
// 测试成年人情况
context.put("age", 25);
StepExecutor executor = flowEngine.getExecutor(StepType.CONDITIONAL);
StepExecutionResult result = executor.execute(conditionalStep, context);
assertEquals(FlowExecutionResult.Status.SUCCESS, result.getStatus());
assertEquals("成年人处理", context.get("result"));
// 测试未成年人情况
context.clear();
context.put("age", 16);
result = executor.execute(conditionalStep, context);
assertEquals(FlowExecutionResult.Status.SUCCESS, result.getStatus());
assertEquals("未成年人处理", context.get("result"));
}
@Test
public void testParallelExecutor() {
// 创建并行步骤
StepDefinition parallelStep = StepDefinitionBuilder
.builder("parallel-tasks", StepType.PARALLEL)
.config("timeoutSeconds", 10)
.config("steps", Arrays.asList(
StepDefinitionBuilder
.builder("task1", StepType.SIMPLE)
.config("action", "sleep")
.config("value", 100)
.build(),
StepDefinitionBuilder
.builder("task2", StepType.SIMPLE)
.config("action", "sleep")
.config("value", 200)
.build()
))
.build();
long startTime = System.currentTimeMillis();
StepExecutor executor = flowEngine.getExecutor(StepType.PARALLEL);
StepExecutionResult result = executor.execute(parallelStep, context);
long endTime = System.currentTimeMillis();
assertEquals(FlowExecutionResult.Status.SUCCESS, result.getStatus());
assertTrue("并行执行应该比串行执行快", endTime - startTime < 250);
ParallelStepExecutor.ParallelExecutionResult parallelResult =
(ParallelStepExecutor.ParallelExecutionResult) result.getResult();
assertEquals(2, parallelResult.getResults().size());
assertFalse(parallelResult.hasFailures());
}
@Test
public void testLoopExecutor() {
// 创建循环步骤
StepDefinition loopStep = StepDefinitionBuilder
.builder("counter-loop", StepType.LOOP)
.config("condition", "context.get('counter', 0) < 5")
.config("maxIterations", 10)
.config("steps", Arrays.asList(
StepDefinitionBuilder
.builder("increment", StepType.SIMPLE)
.config("action", "increment")
.config("value", "counter")
.config("targetKey", "counter")
.build()
))
.build();
context.put("counter", 0);
StepExecutor executor = flowEngine.getExecutor(StepType.LOOP);
StepExecutionResult result = executor.execute(loopStep, context);
assertEquals(FlowExecutionResult.Status.SUCCESS, result.getStatus());
assertEquals(5, (int) context.get("counter"));
LoopStepExecutor.LoopExecutionResult loopResult =
(LoopStepExecutor.LoopExecutionResult) result.getResult();
assertEquals(5, loopResult.getTotalIterations());
}
@Test
public void testScriptExecutor() {
// 创建脚本步骤
StepDefinition scriptStep = StepDefinitionBuilder
.builder("calculate", StepType.SCRIPT)
.config("scriptType", "javascript")
.config("script", """
var a = context.get('a');
var b = context.get('b');
var result = a + b;
context.put('sum', result);
result;
""")
.build();
context.put("a", 10);
context.put("b", 20);
StepExecutor executor = flowEngine.getExecutor(StepType.SCRIPT);
StepExecutionResult result = executor.execute(scriptStep, context);
assertEquals(FlowExecutionResult.Status.SUCCESS, result.getStatus());
assertEquals(30, result.getResult());
assertEquals(30, (int) context.get("sum"));
}
}
🎯 设计亮点
✨ 1. 模板方法模式
- 🏗️ 统一的执行流程: AbstractStepExecutor定义了标准的执行模板
- 🔧 灵活的扩展点: 子类只需实现核心逻辑
- 🛡️ 统一的异常处理: 在基类中处理通用的异常情况
✨ 2. 策略模式
- 🎯 可插拔的执行器: 不同类型的步骤使用不同的执行策略
- 🔄 运行时选择: 根据步骤类型动态选择执行器
- 🚀 易于扩展: 添加新的步骤类型只需实现新的执行器
✨ 3. 组合模式
- 🌳 递归执行: 复杂步骤可以包含子步骤
- 🔀 统一接口: 简单步骤和复合步骤使用相同的接口
- 📊 层次结构: 支持任意深度的步骤嵌套
✨ 4. 并发安全
- 🧵 线程安全: 使用线程安全的数据结构
- 🔒 上下文隔离: 并行执行时创建独立的子上下文
- ⚡ 异步支持: 支持异步和并行执行
🎉 小结
在这一章中,我们完成了:
- 🏗️ 设计了执行器架构: 基于AbstractStepExecutor的可扩展架构
- 🔀 实现了条件执行器: 支持基于表达式的条件分支
- ⚡ 实现了并行执行器: 支持多任务并行执行
- 🔄 实现了循环执行器: 支持条件循环和迭代控制
- 📝 实现了脚本执行器: 支持多种脚本语言的动态执行
- 🧪 提供了完整测试: 验证各种执行器的功能
🚀 下一步
在下一章《上下文管理机制》中,我们将:
- 📦 深入设计FlowContext的实现
- 🔒 实现线程安全的上下文管理
- 🌳 设计层次化的上下文结构
- 🔄 实现上下文的序列化和持久化
- 🧪 编写上下文管理的完整测试
💡 思考题:
- 如何设计执行器的优先级和选择策略?
- 如何实现执行器的热插拔和动态加载?
- 如何设计才能支持执行器的配置和参数化?