08 - Spring Boot集成实现 🌱

🎯 目标: 实现与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接口

监控集成 : 健康检查和指标收集

扩展友好: 支持自定义组件注入

下一章我们将实现监控和日志系统,提供全面的可观测性支持。 📊

相关推荐
舒一笑23 分钟前
如何优雅统计知识库文件个数与子集下不同文件夹文件个数
后端·mysql·程序员
IT果果日记25 分钟前
flink+dolphinscheduler+dinky打造自动化数仓平台
大数据·后端·flink
Java技术小馆36 分钟前
InheritableThreadLoca90%开发者踩过的坑
后端·面试·github
寒士obj1 小时前
Spring容器Bean的创建流程
java·后端·spring
数字人直播2 小时前
视频号数字人直播带货,青否数字人提供全套解决方案!
前端·javascript·后端
shark_chili2 小时前
提升Java开发效率的秘密武器:Jadx反编译工具详解
后端
武子康2 小时前
大数据-75 Kafka 高水位线 HW 与日志末端 LEO 全面解析:副本同步与消费一致性核心
大数据·后端·kafka
YANGZHAO2 小时前
Docker零基础入门:一文搞定容器化核心技能
后端·docker
字节跳跃者2 小时前
SpringBoot + MinIO + kkFile 实现文件预览,这样操作更安全!
java·后端·程序员
我是哪吒2 小时前
分布式微服务系统架构第167集:从零到能跑kafka-redis实战
后端·面试·github