🎯 目标: 实现与Spring Boot的无缝集成,提供自动配置和便捷的使用方式
🤔 为什么需要Spring Boot集成?
Spring Boot集成为流程编排框架带来了巨大价值:
- 🚀 开箱即用: 自动配置,零配置启动
- 🔧 依赖注入: 充分利用Spring的IoC容器
- 📊 监控集成: 与Spring Boot Actuator集成
- 🔒 安全集成: 与Spring Security无缝配合
- 🌐 Web集成: 提供REST API和管理界面
- 📝 配置管理: 利用Spring Boot的配置体系
🏗️ Spring Boot集成架构
graph TB
subgraph "Spring Boot应用层 🌱"
A1[FlowController]
A2[FlowManagementController]
A3[FlowMonitoringController]
A4[FlowWebSocketHandler]
end
subgraph "自动配置层 ⚙️"
B1[FlowAutoConfiguration]
B2[FlowWebAutoConfiguration]
B3[FlowActuatorAutoConfiguration]
B4[FlowSecurityAutoConfiguration]
end
subgraph "服务层 🔧"
C1[FlowService]
C2[FlowDefinitionService]
C3[FlowExecutionService]
C4[FlowMonitoringService]
end
subgraph "核心引擎层 🎯"
D1[FlowEngine]
D2[StepExecutor]
D3[ExpressionEvaluator]
D4[YamlFlowParser]
end
subgraph "存储层 💾"
E1[FlowDefinitionRepository]
E2[FlowExecutionRepository]
E3[FlowMetricsRepository]
E4[ConfigurationProperties]
end
subgraph "监控层 📊"
F1[FlowMetrics]
F2[FlowHealthIndicator]
F3[FlowEndpoint]
F4[FlowEventListener]
end
A1 --> C1
A2 --> C2
A3 --> C4
A4 --> F4
B1 --> C1
B1 --> D1
B2 --> A1
B3 --> F1
B4 --> A1
C1 --> D1
C2 --> D4
C3 --> D1
C4 --> F1
D1 --> D2
D1 --> D3
C2 --> E1
C3 --> E2
C4 --> E3
F1 --> F2
F2 --> F3
⚙️ 自动配置实现
🎯 核心自动配置
java
/**
* 流程编排框架自动配置
*/
@Configuration
@EnableConfigurationProperties({FlowProperties.class, FlowEngineProperties.class})
@ConditionalOnClass(FlowEngine.class)
@AutoConfigureAfter({DataSourceAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class})
public class FlowAutoConfiguration {
private static final Logger logger = LoggerFactory.getLogger(FlowAutoConfiguration.class);
@Bean
@ConditionalOnMissingBean
public ExpressionEvaluator expressionEvaluator(FlowEngineProperties properties) {
SimpleExpressionEvaluator evaluator = new SimpleExpressionEvaluator();
// 配置表达式引擎
if (properties.getExpression().isEnableScriptEngine()) {
evaluator.enableScriptEngine(properties.getExpression().getSupportedLanguages());
}
if (properties.getExpression().isEnableSecurity()) {
evaluator.setSecurityManager(new DefaultSecurityManager());
}
logger.info("配置表达式引擎: {}", evaluator.getClass().getSimpleName());
return evaluator;
}
@Bean
@ConditionalOnMissingBean
public YamlFlowParser yamlFlowParser(ExpressionEvaluator expressionEvaluator) {
FlowConfigValidator validator = new DefaultFlowConfigValidator(expressionEvaluator);
DefaultYamlFlowParser parser = new DefaultYamlFlowParser(validator, expressionEvaluator);
logger.info("配置YAML流程解析器");
return parser;
}
@Bean
@ConditionalOnMissingBean
public FlowEngine flowEngine(ExpressionEvaluator expressionEvaluator,
FlowEngineProperties properties,
@Autowired(required = false) List<StepExecutor> customExecutors,
@Autowired(required = false) List<FlowExecutionListener> listeners) {
DefaultFlowEngine engine = new DefaultFlowEngine(expressionEvaluator);
// 注册自定义执行器
if (customExecutors != null) {
for (StepExecutor executor : customExecutors) {
engine.registerStepExecutor(executor);
logger.info("注册自定义步骤执行器: {}", executor.getClass().getSimpleName());
}
}
// 注册事件监听器
if (listeners != null) {
for (FlowExecutionListener listener : listeners) {
engine.addExecutionListener(listener);
logger.info("注册流程执行监听器: {}", listener.getClass().getSimpleName());
}
}
// 配置引擎参数
engine.setMaxConcurrentFlows(properties.getMaxConcurrentFlows());
engine.setDefaultTimeout(properties.getDefaultTimeout());
engine.setEnableMetrics(properties.isEnableMetrics());
logger.info("配置流程引擎完成");
return engine;
}
@Bean
@ConditionalOnMissingBean
public FlowDefinitionService flowDefinitionService(YamlFlowParser parser,
@Autowired(required = false) FlowDefinitionRepository repository) {
if (repository != null) {
return new JpaFlowDefinitionService(repository, parser);
} else {
return new InMemoryFlowDefinitionService(parser);
}
}
@Bean
@ConditionalOnMissingBean
public FlowExecutionService flowExecutionService(FlowEngine engine,
FlowDefinitionService definitionService,
@Autowired(required = false) FlowExecutionRepository repository) {
if (repository != null) {
return new JpaFlowExecutionService(engine, definitionService, repository);
} else {
return new InMemoryFlowExecutionService(engine, definitionService);
}
}
@Bean
@ConditionalOnMissingBean
public FlowService flowService(FlowDefinitionService definitionService,
FlowExecutionService executionService) {
return new DefaultFlowService(definitionService, executionService);
}
/**
* 默认步骤执行器配置
*/
@Configuration
@ConditionalOnMissingBean(StepExecutor.class)
static class DefaultStepExecutorConfiguration {
@Bean
public SimpleStepExecutor simpleStepExecutor() {
return new SimpleStepExecutor();
}
@Bean
@ConditionalOnClass(name = "org.springframework.context.ApplicationContext")
public ServiceStepExecutor serviceStepExecutor(ApplicationContext applicationContext) {
return new ServiceStepExecutor(applicationContext);
}
@Bean
public ConditionalStepExecutor conditionalStepExecutor(ExpressionEvaluator expressionEvaluator) {
return new ConditionalStepExecutor(expressionEvaluator);
}
@Bean
public ParallelStepExecutor parallelStepExecutor() {
return new ParallelStepExecutor();
}
@Bean
public LoopStepExecutor loopStepExecutor(ExpressionEvaluator expressionEvaluator) {
return new LoopStepExecutor(expressionEvaluator);
}
@Bean
public ScriptStepExecutor scriptStepExecutor(ExpressionEvaluator expressionEvaluator) {
return new ScriptStepExecutor(expressionEvaluator);
}
}
}
/**
* Web相关自动配置
*/
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({DispatcherServlet.class, FlowController.class})
@EnableConfigurationProperties(FlowWebProperties.class)
public class FlowWebAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public FlowController flowController(FlowService flowService) {
return new FlowController(flowService);
}
@Bean
@ConditionalOnMissingBean
public FlowManagementController flowManagementController(FlowDefinitionService definitionService) {
return new FlowManagementController(definitionService);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(name = "simple.flow.web.monitoring.enabled", havingValue = "true", matchIfMissing = true)
public FlowMonitoringController flowMonitoringController(FlowMonitoringService monitoringService) {
return new FlowMonitoringController(monitoringService);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(name = "simple.flow.web.websocket.enabled", havingValue = "true")
public FlowWebSocketHandler flowWebSocketHandler(FlowExecutionService executionService) {
return new FlowWebSocketHandler(executionService);
}
@Configuration
@ConditionalOnProperty(name = "simple.flow.web.websocket.enabled", havingValue = "true")
static class WebSocketConfiguration implements WebSocketConfigurer {
@Autowired
private FlowWebSocketHandler flowWebSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(flowWebSocketHandler, "/flow/websocket")
.setAllowedOrigins("*")
.withSockJS();
}
}
}
/**
* Actuator集成自动配置
*/
@Configuration
@ConditionalOnClass({Endpoint.class, FlowEngine.class})
@ConditionalOnProperty(name = "management.endpoints.web.exposure.include", havingValue = "flow", matchIfMissing = false)
@EnableConfigurationProperties(FlowActuatorProperties.class)
public class FlowActuatorAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public FlowHealthIndicator flowHealthIndicator(FlowEngine engine) {
return new FlowHealthIndicator(engine);
}
@Bean
@ConditionalOnMissingBean
public FlowEndpoint flowEndpoint(FlowService flowService) {
return new FlowEndpoint(flowService);
}
@Bean
@ConditionalOnMissingBean
public FlowMetrics flowMetrics(MeterRegistry meterRegistry, FlowEngine engine) {
return new FlowMetrics(meterRegistry, engine);
}
@Bean
@ConditionalOnMissingBean
public FlowMonitoringService flowMonitoringService(FlowMetrics metrics,
@Autowired(required = false) FlowExecutionRepository repository) {
if (repository != null) {
return new JpaFlowMonitoringService(metrics, repository);
} else {
return new InMemoryFlowMonitoringService(metrics);
}
}
}
📝 配置属性定义
java
/**
* 流程框架配置属性
*/
@ConfigurationProperties(prefix = "simple.flow")
@Data
public class FlowProperties {
/**
* 是否启用流程框架
*/
private boolean enabled = true;
/**
* 流程定义文件路径
*/
private String definitionPath = "classpath:flows/";
/**
* 是否自动加载流程定义
*/
private boolean autoLoad = true;
/**
* 流程定义文件模式
*/
private List<String> definitionPatterns = Arrays.asList("**/*.yaml", "**/*.yml");
/**
* 是否启用开发模式
*/
private boolean devMode = false;
/**
* 是否启用热重载
*/
private boolean hotReload = false;
}
/**
* 流程引擎配置属性
*/
@ConfigurationProperties(prefix = "simple.flow.engine")
@Data
public class FlowEngineProperties {
/**
* 最大并发流程数
*/
private int maxConcurrentFlows = 100;
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 是否启用指标收集
*/
private boolean enableMetrics = true;
/**
* 线程池配置
*/
private ThreadPool threadPool = new ThreadPool();
/**
* 表达式引擎配置
*/
private Expression expression = new Expression();
/**
* 缓存配置
*/
private Cache cache = new Cache();
@Data
public static class ThreadPool {
/**
* 核心线程数
*/
private int coreSize = 10;
/**
* 最大线程数
*/
private int maxSize = 50;
/**
* 队列容量
*/
private int queueCapacity = 1000;
/**
* 线程空闲时间(秒)
*/
private int keepAliveSeconds = 60;
/**
* 线程名前缀
*/
private String threadNamePrefix = "flow-executor-";
}
@Data
public static class Expression {
/**
* 是否启用脚本引擎
*/
private boolean enableScriptEngine = true;
/**
* 支持的脚本语言
*/
private List<String> supportedLanguages = Arrays.asList("javascript", "groovy");
/**
* 是否启用安全管理器
*/
private boolean enableSecurity = true;
/**
* 脚本执行超时时间(毫秒)
*/
private long scriptTimeout = 5000;
/**
* 最大内存使用(字节)
*/
private long maxMemoryUsage = 10 * 1024 * 1024; // 10MB
}
@Data
public static class Cache {
/**
* 是否启用缓存
*/
private boolean enabled = true;
/**
* 缓存类型
*/
private String type = "caffeine";
/**
* 最大缓存条目数
*/
private int maxSize = 1000;
/**
* 缓存过期时间(秒)
*/
private long expireAfterWrite = 3600;
/**
* 缓存访问过期时间(秒)
*/
private long expireAfterAccess = 1800;
}
}
/**
* Web配置属性
*/
@ConfigurationProperties(prefix = "simple.flow.web")
@Data
public class FlowWebProperties {
/**
* 是否启用Web功能
*/
private boolean enabled = true;
/**
* API路径前缀
*/
private String pathPrefix = "/api/flow";
/**
* 是否启用跨域
*/
private boolean enableCors = true;
/**
* 允许的跨域来源
*/
private List<String> allowedOrigins = Arrays.asList("*");
/**
* 监控配置
*/
private Monitoring monitoring = new Monitoring();
/**
* WebSocket配置
*/
private WebSocket websocket = new WebSocket();
@Data
public static class Monitoring {
/**
* 是否启用监控
*/
private boolean enabled = true;
/**
* 监控路径
*/
private String path = "/monitoring";
/**
* 是否需要认证
*/
private boolean requireAuth = false;
}
@Data
public static class WebSocket {
/**
* 是否启用WebSocket
*/
private boolean enabled = false;
/**
* WebSocket路径
*/
private String path = "/websocket";
/**
* 消息缓冲区大小
*/
private int messageBufferSize = 8192;
/**
* 空闲超时时间(毫秒)
*/
private long idleTimeout = 60000;
}
}
/**
* Actuator配置属性
*/
@ConfigurationProperties(prefix = "simple.flow.actuator")
@Data
public class FlowActuatorProperties {
/**
* 是否启用Actuator集成
*/
private boolean enabled = true;
/**
* 健康检查配置
*/
private Health health = new Health();
/**
* 指标配置
*/
private Metrics metrics = new Metrics();
@Data
public static class Health {
/**
* 是否启用健康检查
*/
private boolean enabled = true;
/**
* 健康检查超时时间(毫秒)
*/
private long timeout = 5000;
/**
* 是否显示详细信息
*/
private boolean showDetails = true;
}
@Data
public static class Metrics {
/**
* 是否启用指标收集
*/
private boolean enabled = true;
/**
* 指标名称前缀
*/
private String prefix = "flow";
/**
* 是否启用JVM指标
*/
private boolean enableJvmMetrics = true;
/**
* 是否启用系统指标
*/
private boolean enableSystemMetrics = true;
}
}
🌐 Web控制器实现
java
/**
* 流程执行控制器
*/
@RestController
@RequestMapping("${simple.flow.web.path-prefix:/api/flow}")
@CrossOrigin(origins = "${simple.flow.web.allowed-origins:*}")
@Validated
public class FlowController {
private static final Logger logger = LoggerFactory.getLogger(FlowController.class);
private final FlowService flowService;
public FlowController(FlowService flowService) {
this.flowService = flowService;
}
/**
* 执行流程
*/
@PostMapping("/execute/{flowId}")
public ResponseEntity<FlowExecutionResult> executeFlow(
@PathVariable @NotBlank String flowId,
@RequestBody(required = false) Map<String, Object> inputs) {
try {
logger.info("开始执行流程: {}, 输入参数: {}", flowId, inputs);
FlowExecutionResult result = flowService.executeFlow(flowId, inputs);
logger.info("流程执行完成: {}, 状态: {}", flowId, result.getStatus());
return ResponseEntity.ok(result);
} catch (FlowNotFoundException e) {
logger.warn("流程不存在: {}", flowId);
return ResponseEntity.notFound().build();
} catch (FlowExecutionException e) {
logger.error("流程执行失败: {}", flowId, e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(FlowExecutionResult.error(e.getMessage()));
}
}
/**
* 异步执行流程
*/
@PostMapping("/execute-async/{flowId}")
public ResponseEntity<AsyncFlowExecution> executeFlowAsync(
@PathVariable @NotBlank String flowId,
@RequestBody(required = false) Map<String, Object> inputs) {
try {
logger.info("开始异步执行流程: {}", flowId);
CompletableFuture<FlowExecutionResult> future = flowService.executeFlowAsync(flowId, inputs);
String executionId = UUID.randomUUID().toString();
AsyncFlowExecution execution = AsyncFlowExecution.builder()
.executionId(executionId)
.flowId(flowId)
.status("RUNNING")
.startTime(Instant.now())
.build();
return ResponseEntity.accepted().body(execution);
} catch (FlowNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
/**
* 获取流程执行状态
*/
@GetMapping("/execution/{executionId}")
public ResponseEntity<FlowExecutionStatus> getExecutionStatus(
@PathVariable @NotBlank String executionId) {
Optional<FlowExecutionStatus> status = flowService.getExecutionStatus(executionId);
return status.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
/**
* 停止流程执行
*/
@PostMapping("/execution/{executionId}/stop")
public ResponseEntity<Void> stopExecution(
@PathVariable @NotBlank String executionId) {
try {
flowService.stopExecution(executionId);
return ResponseEntity.ok().build();
} catch (ExecutionNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
/**
* 获取流程列表
*/
@GetMapping("/flows")
public ResponseEntity<List<FlowInfo>> getFlows(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
List<FlowInfo> flows = flowService.getFlows(page, size);
return ResponseEntity.ok(flows);
}
/**
* 获取流程详情
*/
@GetMapping("/flows/{flowId}")
public ResponseEntity<FlowDefinition> getFlow(@PathVariable @NotBlank String flowId) {
try {
FlowDefinition flow = flowService.getFlowDefinition(flowId);
return ResponseEntity.ok(flow);
} catch (FlowNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
/**
* 验证流程定义
*/
@PostMapping("/validate")
public ResponseEntity<ValidationResult> validateFlow(@RequestBody @NotBlank String yamlContent) {
ValidationResult result = flowService.validateFlowDefinition(yamlContent);
return ResponseEntity.ok(result);
}
/**
* 全局异常处理
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationException(MethodArgumentNotValidException e) {
String message = e.getBindingResult().getFieldErrors().stream()
.map(error -> error.getField() + ": " + error.getDefaultMessage())
.collect(Collectors.joining(", "));
ErrorResponse error = ErrorResponse.builder()
.code("VALIDATION_ERROR")
.message(message)
.timestamp(Instant.now())
.build();
return ResponseEntity.badRequest().body(error);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGenericException(Exception e) {
logger.error("未处理的异常", e);
ErrorResponse error = ErrorResponse.builder()
.code("INTERNAL_ERROR")
.message("内部服务器错误")
.timestamp(Instant.now())
.build();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
/**
* 流程管理控制器
*/
@RestController
@RequestMapping("${simple.flow.web.path-prefix:/api/flow}/management")
@CrossOrigin(origins = "${simple.flow.web.allowed-origins:*}")
public class FlowManagementController {
private final FlowDefinitionService definitionService;
public FlowManagementController(FlowDefinitionService definitionService) {
this.definitionService = definitionService;
}
/**
* 创建流程定义
*/
@PostMapping("/definitions")
public ResponseEntity<FlowDefinition> createFlowDefinition(@RequestBody @NotBlank String yamlContent) {
try {
FlowDefinition definition = definitionService.createFromYaml(yamlContent);
return ResponseEntity.status(HttpStatus.CREATED).body(definition);
} catch (FlowParseException e) {
return ResponseEntity.badRequest().build();
}
}
/**
* 更新流程定义
*/
@PutMapping("/definitions/{flowId}")
public ResponseEntity<FlowDefinition> updateFlowDefinition(
@PathVariable @NotBlank String flowId,
@RequestBody @NotBlank String yamlContent) {
try {
FlowDefinition definition = definitionService.updateFromYaml(flowId, yamlContent);
return ResponseEntity.ok(definition);
} catch (FlowNotFoundException e) {
return ResponseEntity.notFound().build();
} catch (FlowParseException e) {
return ResponseEntity.badRequest().build();
}
}
/**
* 删除流程定义
*/
@DeleteMapping("/definitions/{flowId}")
public ResponseEntity<Void> deleteFlowDefinition(@PathVariable @NotBlank String flowId) {
try {
definitionService.deleteFlow(flowId);
return ResponseEntity.noContent().build();
} catch (FlowNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
/**
* 启用/禁用流程
*/
@PostMapping("/definitions/{flowId}/toggle")
public ResponseEntity<Void> toggleFlowDefinition(
@PathVariable @NotBlank String flowId,
@RequestParam boolean enabled) {
try {
if (enabled) {
definitionService.enableFlow(flowId);
} else {
definitionService.disableFlow(flowId);
}
return ResponseEntity.ok().build();
} catch (FlowNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
/**
* 重新加载流程定义
*/
@PostMapping("/reload")
public ResponseEntity<ReloadResult> reloadFlowDefinitions() {
ReloadResult result = definitionService.reloadAll();
return ResponseEntity.ok(result);
}
}
📊 监控和健康检查
java
/**
* 流程健康指示器
*/
@Component
public class FlowHealthIndicator implements HealthIndicator {
private final FlowEngine engine;
private final FlowActuatorProperties properties;
public FlowHealthIndicator(FlowEngine engine, FlowActuatorProperties properties) {
this.engine = engine;
this.properties = properties;
}
@Override
public Health health() {
try {
// 检查引擎状态
if (!engine.isRunning()) {
return Health.down()
.withDetail("engine", "stopped")
.build();
}
// 检查资源使用情况
EngineStatus status = engine.getStatus();
Health.Builder builder = Health.up()
.withDetail("engine", "running")
.withDetail("activeFlows", status.getActiveFlowCount())
.withDetail("totalExecuted", status.getTotalExecutedCount())
.withDetail("successRate", status.getSuccessRate());
// 检查资源使用率
if (status.getCpuUsage() > 0.9) {
builder.status("WARN")
.withDetail("warning", "High CPU usage: " + status.getCpuUsage());
}
if (status.getMemoryUsage() > 0.9) {
builder.status("WARN")
.withDetail("warning", "High memory usage: " + status.getMemoryUsage());
}
return builder.build();
} catch (Exception e) {
return Health.down()
.withDetail("error", e.getMessage())
.build();
}
}
}
/**
* 流程监控端点
*/
@Endpoint(id = "flow")
public class FlowEndpoint {
private final FlowService flowService;
public FlowEndpoint(FlowService flowService) {
this.flowService = flowService;
}
@ReadOperation
public Map<String, Object> flow() {
Map<String, Object> info = new HashMap<>();
// 基本信息
info.put("version", getClass().getPackage().getImplementationVersion());
info.put("status", "running");
info.put("timestamp", Instant.now());
// 流程统计
FlowStatistics stats = flowService.getStatistics();
info.put("statistics", Map.of(
"totalFlows", stats.getTotalFlows(),
"activeExecutions", stats.getActiveExecutions(),
"completedExecutions", stats.getCompletedExecutions(),
"failedExecutions", stats.getFailedExecutions(),
"averageExecutionTime", stats.getAverageExecutionTime()
));
return info;
}
@ReadOperation
public Map<String, Object> flows() {
List<FlowInfo> flows = flowService.getFlows(0, Integer.MAX_VALUE);
return Map.of(
"total", flows.size(),
"flows", flows.stream()
.map(flow -> Map.of(
"id", flow.getId(),
"name", flow.getName(),
"status", flow.getStatus(),
"lastExecuted", flow.getLastExecuted(),
"executionCount", flow.getExecutionCount()
))
.collect(Collectors.toList())
);
}
@WriteOperation
public Map<String, Object> reload() {
ReloadResult result = flowService.reloadFlowDefinitions();
return Map.of(
"success", result.isSuccess(),
"reloadedCount", result.getReloadedCount(),
"failedCount", result.getFailedCount(),
"errors", result.getErrors()
);
}
}
/**
* 流程指标收集器
*/
@Component
public class FlowMetrics implements FlowExecutionListener {
private final MeterRegistry meterRegistry;
private final Counter executionCounter;
private final Counter successCounter;
private final Counter failureCounter;
private final Timer executionTimer;
private final Gauge activeFlowsGauge;
public FlowMetrics(MeterRegistry meterRegistry, FlowEngine engine) {
this.meterRegistry = meterRegistry;
// 注册指标
this.executionCounter = Counter.builder("flow.executions.total")
.description("Total number of flow executions")
.register(meterRegistry);
this.successCounter = Counter.builder("flow.executions.success")
.description("Number of successful flow executions")
.register(meterRegistry);
this.failureCounter = Counter.builder("flow.executions.failure")
.description("Number of failed flow executions")
.register(meterRegistry);
this.executionTimer = Timer.builder("flow.execution.duration")
.description("Flow execution duration")
.register(meterRegistry);
this.activeFlowsGauge = Gauge.builder("flow.executions.active")
.description("Number of active flow executions")
.register(meterRegistry, engine, e -> e.getStatus().getActiveFlowCount());
// 注册为监听器
engine.addExecutionListener(this);
}
@Override
public void onFlowStarted(FlowExecutionEvent event) {
executionCounter.increment(
Tags.of(
"flow.id", event.getFlowId(),
"flow.name", event.getFlowName()
)
);
}
@Override
public void onFlowCompleted(FlowExecutionEvent event) {
Tags tags = Tags.of(
"flow.id", event.getFlowId(),
"flow.name", event.getFlowName()
);
if (event.getResult().isSuccess()) {
successCounter.increment(tags);
} else {
failureCounter.increment(tags.and("error.type", event.getResult().getErrorType()));
}
executionTimer.record(event.getExecutionTime(), TimeUnit.MILLISECONDS, tags);
}
@Override
public void onStepStarted(StepExecutionEvent event) {
Counter.builder("flow.steps.total")
.tags(
"flow.id", event.getFlowId(),
"step.id", event.getStepId(),
"step.type", event.getStepType().name()
)
.register(meterRegistry)
.increment();
}
@Override
public void onStepCompleted(StepExecutionEvent event) {
Tags tags = Tags.of(
"flow.id", event.getFlowId(),
"step.id", event.getStepId(),
"step.type", event.getStepType().name()
);
if (event.getResult().isSuccess()) {
Counter.builder("flow.steps.success")
.tags(tags)
.register(meterRegistry)
.increment();
} else {
Counter.builder("flow.steps.failure")
.tags(tags.and("error.type", event.getResult().getErrorType()))
.register(meterRegistry)
.increment();
}
Timer.builder("flow.step.duration")
.tags(tags)
.register(meterRegistry)
.record(event.getExecutionTime(), TimeUnit.MILLISECONDS);
}
}
🧪 Spring Boot集成测试
java
@SpringBootTest
@TestPropertySource(properties = {
"simple.flow.enabled=true",
"simple.flow.definition-path=classpath:test-flows/",
"simple.flow.engine.max-concurrent-flows=10",
"simple.flow.web.enabled=true"
})
public class FlowSpringBootIntegrationTest {
@Autowired
private FlowService flowService;
@Autowired
private FlowController flowController;
@Autowired
private TestRestTemplate restTemplate;
@LocalServerPort
private int port;
@Test
public void testAutoConfiguration() {
assertNotNull(flowService);
assertNotNull(flowController);
}
@Test
public void testFlowExecution() {
// 创建测试流程
String yaml = """
version: "1.0"
flows:
- id: "test-flow"
name: "测试流程"
steps:
- id: "step1"
name: "第一步"
type: "SIMPLE"
""";
FlowDefinition definition = flowService.createFlowFromYaml(yaml);
assertNotNull(definition);
// 执行流程
FlowExecutionResult result = flowService.executeFlow("test-flow", Map.of());
assertTrue(result.isSuccess());
}
@Test
public void testRestApi() {
String url = "http://localhost:" + port + "/api/flow/flows";
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@Test
public void testHealthIndicator() {
String url = "http://localhost:" + port + "/actuator/health/flow";
ResponseEntity<Map> response = restTemplate.getForEntity(url, Map.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
Map<String, Object> health = response.getBody();
assertEquals("UP", health.get("status"));
}
@Test
public void testFlowEndpoint() {
String url = "http://localhost:" + port + "/actuator/flow";
ResponseEntity<Map> response = restTemplate.getForEntity(url, Map.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
Map<String, Object> info = response.getBody();
assertTrue(info.containsKey("statistics"));
assertTrue(info.containsKey("version"));
}
}
🎯 设计亮点
🚀 开箱即用
- 自动配置: 零配置启动,智能默认值
- 条件装配: 根据环境自动选择组件
- 配置绑定: 类型安全的配置属性
- 热重载: 开发模式下支持配置热重载
🔧 灵活集成
- 可选依赖: 根据classpath自动启用功能
- 扩展点: 支持自定义执行器和监听器
- 多存储: 支持内存、JPA等多种存储方式
- 多环境: 支持不同环境的配置
📊 完善监控
- 健康检查: 集成Spring Boot Actuator
- 指标收集: 与Micrometer集成
- 端点暴露: 提供管理和监控端点
- 实时监控: WebSocket实时推送
🌐 Web友好
- RESTful API: 标准的REST接口
- 异常处理: 统一的异常处理机制
- 参数验证: 集成Bean Validation
- 跨域支持: 可配置的CORS支持
📝 本章小结
本章实现了与Spring Boot的深度集成,具备以下特性:
✅ 完整的自动配置 : 支持零配置启动
✅ 丰富的配置选项 : 类型安全的配置属性
✅ RESTful API : 完整的Web接口
✅ 监控集成 : 健康检查和指标收集
✅ 扩展友好: 支持自定义组件注入
下一章我们将实现监控和日志系统,提供全面的可观测性支持。 📊