首页
/ 从0到1掌握飞龙工作流FlowLong:分布式架构与核心技术解密

从0到1掌握飞龙工作流FlowLong:分布式架构与核心技术解密

2026-02-04 04:46:32作者:姚月梅Lane

为什么选择FlowLong工作流引擎?

你是否还在为中国式复杂审批流程而头疼?传统工作流引擎要么功能过重难以集成,要么不支持中国特色审批场景。飞龙工作流FlowLong作为国产无代码工作流引擎的佼佼者,不仅支持30+种中国特色流程操作,还提供轻量级集成方案,完美适配Spring Boot与Solon生态。本文将深入剖析其架构设计与技术实现,助你快速掌握企业级工作流解决方案。

读完本文你将获得:

  • 理解FlowLong的分层架构设计与核心组件交互
  • 掌握流程引擎的核心技术点:流程定义、实例管理与任务调度
  • 学会使用Spring Boot/Solon快速集成工作流功能
  • 深入了解中国特色审批场景的实现方案
  • 获取性能优化与分布式部署的最佳实践

FlowLong架构设计概览

整体架构图

flowchart TD
    subgraph 接入层
        A[Spring Boot Starter]
        B[Solon Plugin]
    end
    
    subgraph 核心引擎层
        C[FlowLongEngine 引擎接口]
        D[ProcessService 流程定义服务]
        E[RuntimeService 实例服务]
        F[TaskService 任务服务]
        G[QueryService 查询服务]
    end
    
    subgraph 业务逻辑层
        H[流程解析器]
        I[任务创建处理器]
        J[条件节点处理器]
        K[事件监听器]
    end
    
    subgraph 数据访问层
        L[DAO接口]
        M[MyBatis-Plus实现]
    end
    
    subgraph 存储层
        N[MySQL]
        O[PostgreSQL]
        P[Oracle]
    end
    
    A --> C
    B --> C
    C --> D
    C --> E
    C --> F
    C --> G
    D --> H
    E --> I
    F --> J
    G --> L
    H --> K
    I --> K
    J --> K
    L --> M
    M --> N
    M --> O
    M --> P

核心模块功能说明

模块名称 核心功能 关键类
flowlong-core 工作流核心引擎实现 FlowLongEngineImpl、Execution、FlowLongContext
flowlong-spring-boot-starter Spring Boot集成支持 FlowLongAutoConfiguration、SpelFlowLongExpression
flowlong-solon-plugin Solon框架集成支持 XPluginImpl、SolonFlowLongExpression
flowlong-mybatis-plus 数据访问层实现 各DAO接口的MyBatis-Plus实现类
flowlong-spring-boot-example Spring Boot示例 TestController、TestConfig
flowlong-solon-example Solon示例 TestController、FlowLongApplication

技术栈选型

技术领域 选型 优势
核心框架 Java + Maven/Gradle 跨平台、生态丰富
依赖注入 Spring/Solon 轻量级集成、低侵入
ORM框架 MyBatis-Plus 简化CRUD操作、性能优秀
表达式解析 Spring EL/自定义表达式 支持复杂业务规则计算
数据库支持 MySQL/Oracle/PostgreSQL 多数据库适配、企业级支持
缓存机制 本地缓存 提高流程定义查询性能
任务调度 定时任务 支持超时审批、自动提醒

核心组件详解

FlowLongEngine引擎接口

FlowLongEngine作为核心引擎接口,定义了工作流引擎的所有核心操作,包括流程实例的创建、任务执行、跳转与驳回等功能。其设计采用了接口隔离原则,将不同职责的功能划分为多个服务接口。

public interface FlowLongEngine {
    // 流程实例启动方法族
    Optional<FlwInstance> startInstanceById(Long id, FlowCreator flowCreator, Map<String, Object> args, boolean saveAsDraft, Supplier<FlwInstance> supplier);
    
    // 任务执行方法族
    boolean executeTask(Long taskId, FlowCreator flowCreator, Map<String, Object> args);
    
    // 流程跳转方法
    default boolean executeJumpTask(Long taskId, String nodeKey, FlowCreator flowCreator, Map<String, Object> args) {
        return this.executeJumpTask(taskId, nodeKey, flowCreator, args, TaskType.jump).isPresent();
    }
    
    // 驳回操作方法
    Optional<List<FlwTask>> executeRejectTask(FlwTask currentFlwTask, String nodeKey, FlowCreator flowCreator, Map<String, Object> args, boolean termination);
    
    // 更多核心方法...
}

四大核心服务

FlowLong将核心功能划分为四大服务接口,职责清晰,便于扩展:

  1. ProcessService - 流程定义服务

    • 流程部署与版本管理
    • 流程定义查询与删除
    • 模型缓存管理
  2. RuntimeService - 流程实例服务

    • 流程实例创建与启动
    • 实例变量管理
    • 流程重启与终止
  3. TaskService - 任务服务

    • 任务执行与跳转
    • 任务分配与委派
    • 加签与减签操作
  4. QueryService - 查询服务

    • 流程实例查询
    • 任务状态查询
    • 历史数据查询

核心上下文设计

FlowLongContext作为全局上下文,维护了引擎的所有配置与组件引用,采用单例模式确保全局唯一性。

public class FlowLongContext {
    // 服务组件
    private ProcessService processService;
    private RuntimeService runtimeService;
    private TaskService taskService;
    private QueryService queryService;
    
    // 配置参数
    private FlowLongProperties properties;
    
    // 处理器与策略
    private CreateTaskHandler createTaskHandler;
    private ConditionNodeHandler conditionNodeHandler;
    private TaskAccessStrategy taskAccessStrategy;
    
    // 工具类
    private FlowLongExpression flowLongExpression;
    private FlowJsonHandler flowJsonHandler;
    
    // 上下文管理方法...
}

流程引擎核心技术解析

流程定义与解析

FlowLong采用JSON格式定义流程模型,通过ProcessModelParser将JSON转换为内存中的ProcessModel对象。

sequenceDiagram
    participant Client
    participant ProcessService
    participant ProcessModelParser
    participant FlowCache
    participant Repository
    
    Client->>ProcessService: 部署流程定义(JSON)
    ProcessService->>ProcessModelParser: 解析JSON
    ProcessModelParser->>ProcessModel: 构建对象模型
    ProcessModelParser->>FlowCache: 缓存ProcessModel
    ProcessService->>Repository: 保存流程定义

核心解析代码:

public class DefaultProcessModelParser implements ProcessModelParser {
    @Override
    public ProcessModel parse(String content, String cacheKey, boolean redeploy) {
        // 从缓存获取
        ProcessModel processModel = getFlowCache().get(cacheKey);
        if (null != processModel && !redeploy) {
            return processModel;
        }
        
        // JSON解析为ProcessModel对象
        processModel = FlowLongContext.fromJson(content, ProcessModel.class);
        
        // 构建节点关系
        processModel.buildParentNode(processModel.getRootNode());
        
        // 缓存流程模型
        getFlowCache().put(cacheKey, processModel);
        return processModel;
    }
}

流程实例执行流程

流程实例的执行是工作流引擎的核心,涉及状态管理、任务创建、流转控制等关键环节。

flowchart TD
    A[启动流程实例] --> B[解析流程模型]
    B --> C[创建初始任务]
    C --> D[任务分配给处理人]
    D --> E[等待任务执行]
    E --> F{任务操作类型}
    F -->|正常通过| G[执行节点出口规则]
    F -->|驳回| H[回退到指定节点]
    F -->|跳转| I[跳转到目标节点]
    G --> J[判断是否结束]
    H --> D
    I --> D
    J -->|是| K[结束流程实例]
    J -->|否| L[创建下一节点任务]
    L --> D

核心执行代码:

public class RuntimeServiceImpl implements RuntimeService {
    @Override
    public FlwInstance createInstance(FlwProcess flwProcess, FlowCreator flowCreator, 
                                     Map<String, Object> args, NodeModel nodeModel,
                                     boolean saveAsDraft, Supplier<FlwInstance> supplier) {
        // 创建流程实例对象
        FlwInstance flwInstance = supplier != null ? supplier.get() : new FlwInstance();
        
        // 设置基本属性
        flwInstance.setProcessId(flwProcess.getId());
        flwInstance.setProcessKey(flwProcess.getProcessKey());
        flwInstance.setProcessName(flwProcess.getProcessName());
        flwInstance.setTenantId(flowCreator.getTenantId());
        flwInstance.setBusinessKey(flwInstance.getBusinessKey());
        flwInstance.setPriority(InstancePriority.DEFAULT);
        
        // 处理变量
        if (MapUtils.isNotEmpty(args)) {
            flwInstance.putAllVariable(args);
        }
        
        // 保存实例
        saveInstance(flwInstance, flwProcess, saveAsDraft, flowCreator);
        
        // 如果不是暂存,则创建初始任务
        if (!saveAsDraft) {
            Execution execution = new Execution();
            execution.setFlowCreator(flowCreator);
            execution.setArgs(args);
            execution.setProcessModel(getProcessModel(flwProcess));
            
            // 创建初始任务
            createStartTask(flwInstance, nodeModel, execution);
        }
        
        return flwInstance;
    }
}

中国特色审批场景实现

FlowLong专为中国特色审批流程设计,支持30+种特殊操作,以下是几种典型场景的实现方案:

会签功能实现

会签功能支持顺序会签、并行会签、或签和票签四种模式,通过PerformType枚举控制行为:

public enum PerformType {
    SEQUENTIAL(1, "顺序会签"),
    PARALLEL(2, "并行会签"),
    OR(3, "或签"),
    VOTE(4, "票签");
    
    private final int value;
    private final String desc;
    
    // 枚举实现...
    
    public static PerformType get(Integer value) {
        if (value == null) {
            return null;
        }
        for (PerformType type : values()) {
            if (type.value == value) {
                return type;
            }
        }
        return null;
    }
}

并行会签处理逻辑:

public void handleParallelSign(Execution execution, NodeModel nodeModel, FlwTask currentTask) {
    // 获取该节点的所有任务
    List<FlwTask> nodeTasks = taskService.getTasksByInstanceIdAndNodeKey(
        currentTask.getInstanceId(), nodeModel.getNodeKey());
    
    // 检查是否所有任务都已完成
    boolean allCompleted = nodeTasks.stream()
        .allMatch(task -> TaskState.COMPLETED.equals(TaskState.get(task.getTaskState())));
    
    // 检查是否有拒绝任务
    boolean hasRejected = nodeTasks.stream()
        .anyMatch(task -> TaskState.REJECT.equals(TaskState.get(task.getTaskState())));
    
    if (hasRejected) {
        // 如有拒绝,执行驳回流程
        execution.setTaskEventType(TaskEventType.REJECT);
        rejectionHandler.handleRejection(execution, currentTask, nodeModel);
    } else if (allCompleted) {
        // 所有同意,继续流程
        execution.setCurrentNodeKey(nodeModel.getNodeKey());
        flowRouter.route(execution);
    }
}

驳回策略实现

FlowLong支持三种驳回策略,通过灵活的节点回溯机制实现:

flowchart TD
    A[当前任务] --> B{驳回策略}
    B -->|退回上一步| C[查找上一节点]
    B -->|退回发起人| D[查找开始节点]
    B -->|任意节点| E[选择目标节点]
    C --> F[创建退回任务]
    D --> F
    E --> F
    F --> G[更新当前流程状态]

快速集成指南

Spring Boot集成步骤

  1. 添加依赖
<dependency>
    <groupId>com.aizuda</groupId>
    <artifactId>flowlong-spring-boot-starter</artifactId>
    <version>最新版本</version>
</dependency>

<!-- 数据库驱动 -->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>
  1. 配置数据库
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/flowlong?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver

flowlong:
  # 流程引擎配置
  process-definition-cache-seconds: 3600
  # 任务分配策略
  task-assign-strategy: role_first
  # 自动审批配置
  auto-approve:
    enabled: true
    expire-time: 86400000
  1. 创建流程定义
@RestController
@RequestMapping("/process")
public class ProcessController {
    
    @Autowired
    private ProcessService processService;
    
    @PostMapping("/deploy")
    public Result deployProcess(@RequestBody ProcessDefinitionRequest request) {
        // 部署流程定义
        FlwProcess process = processService.deploy(
            request.getName(), 
            request.getKey(), 
            request.getJsonDef(),
            FlowCreator.of(SecurityUtils.getCurrentUserId(), SecurityUtils.getCurrentUserName())
        );
        return Result.success(process);
    }
}
  1. 启动流程实例
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private FlowLongEngine flowLongEngine;
    
    @Override
    @Transactional
    public Order createOrder(OrderDTO orderDTO) {
        // 保存订单
        Order order = saveOrder(orderDTO);
        
        // 启动流程实例
        FlowCreator creator = FlowCreator.of(
            SecurityUtils.getCurrentUserId(), 
            SecurityUtils.getCurrentUserName()
        );
        
        // 流程参数
        Map<String, Object> args = new HashMap<>();
        args.put("orderId", order.getId());
        args.put("amount", order.getAmount());
        args.put("assignee", orderDTO.getManagerId());
        
        // 启动流程
        Optional<FlwInstance> instance = flowLongEngine.startInstanceByProcessKey(
            "order_approval",  // 流程定义Key
            creator, 
            args
        );
        
        // 关联流程实例ID
        order.setProcessInstanceId(instance.get().getId());
        orderMapper.updateById(order);
        
        return order;
    }
}
  1. 处理任务
@RestController
@RequestMapping("/task")
public class TaskController {

    @Autowired
    private TaskService taskService;
    
    @PostMapping("/complete")
    public Result completeTask(@RequestBody CompleteTaskRequest request) {
        FlowCreator creator = FlowCreator.of(
            SecurityUtils.getCurrentUserId(), 
            SecurityUtils.getCurrentUserName()
        );
        
        Map<String, Object> args = new HashMap<>();
        args.put("comment", request.getComment());
        args.put("approvalResult", request.getApprovalResult());
        
        boolean success = taskService.executeTask(request.getTaskId(), creator, args);
        return success ? Result.success() : Result.error("任务处理失败");
    }
    
    @PostMapping("/reject")
    public Result rejectTask(@RequestBody RejectTaskRequest request) {
        FlowCreator creator = FlowCreator.of(
            SecurityUtils.getCurrentUserId(), 
            SecurityUtils.getCurrentUserName()
        );
        
        Map<String, Object> args = new HashMap<>();
        args.put("comment", request.getComment());
        
        FlwTask task = taskService.getTaskById(request.getTaskId());
        Optional<List<FlwTask>> result = flowLongEngine.executeRejectTask(
            task, 
            request.getTargetNodeKey(), 
            creator, 
            args
        );
        
        return result.isPresent() ? Result.success() : Result.error("驳回失败");
    }
}

Solon集成示例

Solon集成与Spring Boot类似,主要区别在于 starter 依赖和配置方式:

<dependency>
    <groupId>com.aizuda</groupId>
    <artifactId>flowlong-solon-plugin</artifactId>
    <version>最新版本</version>
</dependency>
@Configuration
public class AppConfig {
    @Bean
    public void flowlongConfig() {
        // Solon中配置FlowLong
        FlowLongContext context = new FlowLongContext();
        context.setFlowLongExpression(new SolonFlowLongExpression());
        context.setFlowJsonHandler(new SolonFlowJsonHandler());
        // 其他配置...
        
        FlowLongEngine engine = new FlowLongEngineImpl().configure(context);
        Aop.wrapAndPut(FlowLongEngine.class, engine);
    }
}

性能优化与分布式部署

性能优化策略

  1. 流程定义缓存

FlowLong默认缓存流程定义到本地内存,减少数据库访问:

@Configuration
public class FlowLongConfig {
    @Bean
    public ProcessModelParser processModelParser() {
        DefaultProcessModelParser parser = new DefaultProcessModelParser();
        // 设置缓存过期时间为2小时
        parser.setCacheSeconds(7200);
        return parser;
    }
}
  1. 数据库优化

关键表索引设计:

-- 任务表索引
CREATE INDEX idx_task_instance_id ON flw_task(instance_id);
CREATE INDEX idx_task_actor_id ON flw_task(actor_id);
CREATE INDEX idx_task_create_time ON flw_task(create_time);

-- 实例表索引
CREATE INDEX idx_instance_business_key ON flw_instance(business_key);
CREATE INDEX idx_instance_process_key ON flw_instance(process_key);
  1. 异步处理

对于耗时操作采用异步处理:

@Service
public class AsyncTaskService {
    @Async
    public CompletableFuture<Void> asyncCompleteTask(Long taskId, FlowCreator creator, Map<String, Object> args) {
        taskService.executeTask(taskId, creator, args);
        return CompletableFuture.runAsync(() -> {
            // 发送通知等后续操作
            notificationService.sendTaskCompletedNotification(taskId);
        });
    }
}

分布式部署方案

在分布式环境下,FlowLong通过数据库悲观锁保证任务操作的原子性:

public class DistributedTaskLock implements TaskLock {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Override
    public boolean tryLock(Long taskId, String userId, long timeout) {
        try {
            // 使用数据库悲观锁
            jdbcTemplate.update(
                "UPDATE flw_task SET lock_user_id = ?, lock_time = NOW() WHERE id = ? AND lock_user_id IS NULL",
                userId, taskId
            );
            
            // 检查是否成功获取锁
            Integer count = jdbcTemplate.queryForObject(
                "SELECT COUNT(*) FROM flw_task WHERE id = ? AND lock_user_id = ?",
                Integer.class, taskId, userId
            );
            
            return count != null && count > 0;
        } catch (Exception e) {
            log.error("获取任务锁失败", e);
            return false;
        }
    }
    
    @Override
    public void releaseLock(Long taskId, String userId) {
        jdbcTemplate.update(
            "UPDATE flw_task SET lock_user_id = NULL, lock_time = NULL WHERE id = ? AND lock_user_id = ?",
            taskId, userId
        );
    }
}

常见问题与解决方案

问题1:任务分配失败

可能原因

  • 流程定义中未正确设置处理人
  • 任务分配策略配置错误
  • 用户/角色信息未正确加载

解决方案

@Configuration
public class TaskAssignConfig {
    @Bean
    public TaskActorProvider taskActorProvider() {
        return new CustomTaskActorProvider();
    }
    
    public static class CustomTaskActorProvider implements TaskActorProvider {
        @Override
        public Integer getActorType(NodeModel nodeModel) {
            // 自定义处理人类型判断逻辑
            if (nodeModel.getExtendConfig().containsKey("roleId")) {
                return ActorType.ROLE.getValue();
            } else if (nodeModel.getExtendConfig().containsKey("deptId")) {
                return ActorType.DEPARTMENT.getValue();
            }
            return ActorType.USER.getValue();
        }
    }
}

问题2:流程实例启动失败

排查步骤

  1. 检查流程定义JSON是否正确
  2. 验证流程模型是否包含开始节点
  3. 检查数据库连接是否正常
  4. 查看日志中的具体错误信息

示例修复:确保流程定义包含正确的开始节点:

{
  "nodeKey": "start",
  "nodeName": "开始",
  "nodeType": "startEvent",
  "nextNodeKeys": ["approve"],
  "extendConfig": {}
}

问题3:并行网关死锁

解决方案:优化并行分支汇聚条件:

public class OptimizedJoinGatewayHandler implements JoinGatewayHandler {
    @Override
    public boolean canProceed(Execution execution, NodeModel nodeModel) {
        String instanceId = execution.getInstanceId();
        String nodeKey = nodeModel.getNodeKey();
        
        // 查询所有进入分支的完成情况
        List<String> incomingNodes = nodeModel.getIncomingNodeKeys();
        long completedCount = incomingNodes.stream()
            .filter(nk -> taskService.countCompletedTasks(instanceId, nk) > 0)
            .count();
        
        // 所有分支完成才继续
        return completedCount == incomingNodes.size();
    }
}

总结与展望

FlowLong作为一款专为中国特色审批流程设计的工作流引擎,通过灵活的架构设计和丰富的功能支持,为企业提供了开箱即用的工作流解决方案。其核心优势在于:

  1. 轻量级架构:无侵入式集成,易于上手和扩展
  2. 丰富的中国特色功能:支持30+种中国式审批场景
  3. 多框架支持:同时支持Spring Boot和Solon生态
  4. 高性能设计:通过缓存和优化查询提升系统性能
  5. 完善的文档和示例:降低学习和使用门槛

未来,FlowLong将继续在以下方向发展:

  • 引入分布式缓存替代本地缓存,提升集群性能
  • 支持流程设计器与引擎的低代码集成
  • 增强AI辅助流程设计功能
  • 提供更多行业解决方案模板

参考资源

  1. 官方文档:https://flowlong.aizuda.com
  2. 设计器在线演示:https://flowlong-desginer.pages.dev
  3. 源码仓库:https://gitcode.com/aizuda/flowlong
  4. 示例项目:flowlong-spring-boot-example 和 flowlong-solon-example

通过本文的介绍,相信你已经对FlowLong的架构设计和核心技术有了深入了解。现在就开始动手实践,将工作流能力集成到你的项目中,提升业务流程的自动化水平和效率!

如果觉得本文对你有帮助,请点赞、收藏并关注作者,获取更多工作流技术干货!下一期我们将深入探讨FlowLong的事件监听机制与扩展点开发,敬请期待。

登录后查看全文
热门项目推荐
相关项目推荐