Chapter 10

实战:电商订单系统

DDD 分层架构,商品/库存/订单/支付完整模块,订单状态机,分布式事务 Seata AT 模式。

DDD 领域驱动设计分层架构

DDD(Domain-Driven Design,领域驱动设计)是应对复杂业务系统的架构方法论,由 Eric Evans 在 2003 年提出。其核心思想是:软件模型应该反映业务领域,而不是技术实现。DDD 将系统分为四层,每层只依赖下层:

┌────────────────────────────────────────────────────────────────┐ │ DDD 分层架构 │ ├────────────────────────────────────────────────────────────────┤ │ Interface Layer(接口层) │ │ └── Controller / GraphQL Resolver / Event Handler │ │ 职责:接收外部请求,参数验证,转换 DTO │ ├────────────────────────────────────────────────────────────────┤ │ Application Layer(应用层) │ │ └── ApplicationService / CommandHandler / QueryHandler │ │ 职责:编排领域服务,管理事务,发布领域事件 │ ├────────────────────────────────────────────────────────────────┤ │ Domain Layer(领域层)⭐ 核心 │ │ └── Entity / AggregateRoot / ValueObject / DomainService │ │ └── Repository(接口)/ DomainEvent │ │ 职责:核心业务规则,与技术无关,可独立测试 │ ├────────────────────────────────────────────────────────────────┤ │ Infrastructure Layer(基础设施层) │ │ └── RepositoryImpl / JPA Entity / Redis / RabbitMQ │ │ 职责:技术实现,持久化,外部系统集成 │ └────────────────────────────────────────────────────────────────┘

核心概念名词解释

聚合根(Aggregate Root)
聚合是一组相关对象的边界,聚合根是聚合的入口。外部只能通过聚合根访问聚合内的对象,这保证了业务规则和数据一致性的边界。Order 就是一个聚合根,OrderItem 只能通过 Order 访问。
值对象(Value Object)
没有唯一标识、通过属性值来判断相等性的对象,且不可变。如 Money(100, "CNY")、Address("上海市浦东新区")。值对象可以安全地共享和复制,修改时需创建新实例。
领域事件(Domain Event)
表示领域中发生的有业务意义的事情,如 OrderCreatedEvent、OrderPaidEvent。领域事件是解耦聚合间通信的关键机制,也是实现最终一致性的基础。
CQRS(命令查询责任分离)
Command Query Responsibility Segregation,将写操作(Command)和读操作(Query)分离到不同的模型。写模型保证业务规则,读模型专注性能优化(如宽表、物化视图)。
Seata AT 模式
阿里巴巴开源的分布式事务框架 Seata 的自动模式(Auto Transaction)。通过代理数据源,自动记录业务 SQL 的前镜像和后镜像,在事务失败时自动生成反向 SQL 进行回滚,对业务代码侵入最小。
最终一致性(Eventual Consistency)
分布式系统中,允许短暂的数据不一致,但最终所有节点会达到一致状态。相比强一致性(同步等待所有节点确认),最终一致性有更好的可用性和性能,是大多数互联网业务可以接受的。

系统模块划分

电商订单系统 │ ├── product-service(商品服务) │ ├── 商品 CRUD、分类管理 │ └── 商品详情查询(高缓存) │ ├── inventory-service(库存服务) │ ├── 库存查询 │ ├── 扣减库存(防超卖) │ └── 库存回滚 │ ├── order-service(订单服务)⭐ 核心 │ ├── 创建订单(协调商品/库存/支付) │ ├── 订单状态机 │ ├── 订单查询(CQRS 读模型) │ └── 分布式事务管理 │ └── payment-service(支付服务) ├── 发起支付 ├── 支付回调处理 └── 退款处理

订单实体与状态机

订单状态机 ┌─────────────────────────────────────────────────┐ │ │ │ [PENDING] ──支付成功──→ [PAID] ──发货──→ [SHIPPED] │ │ │ │ │ 超时取消 支付超时 确认收货 │ │ │ │ │ ▼ ▼ ▼ │ [CANCELLED] [CANCELLED] [COMPLETED] │ │ │ 任意状态────────────────申请退款──→ [REFUNDING] │ │ │ 退款成功 │ │ │ ▼ │ [REFUNDED] └─────────────────────────────────────────────────┘

Order 聚合根实现

@Entity
@Table(name = "orders")
public class Order {  // 聚合根

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true, nullable = false)
    private String orderNo;  // 业务订单号(雪花算法生成)

    private Long userId;

    @Enumerated(EnumType.STRING)
    private OrderStatus status;

    @Embedded
    private Money totalAmount;  // 值对象

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    private List<OrderItem> items = new ArrayList<>();

    @Transient
    private List<DomainEvent> domainEvents = new ArrayList<>();

    // 工厂方法:创建订单(保证不变量)
    public static Order create(Long userId, List<OrderItem> items) {
        Order order = new Order();
        order.userId = userId;
        order.orderNo = SnowflakeIdGenerator.next();
        order.status = OrderStatus.PENDING;
        order.items = items;
        order.totalAmount = calculateTotal(items);
        // 发布领域事件
        order.domainEvents.add(new OrderCreatedEvent(order.orderNo, userId));
        return order;
    }

    // 支付成功(状态转换由聚合根控制)
    public void markPaid(String paymentId) {
        if (this.status != OrderStatus.PENDING) {
            throw new BusinessException("只有待支付订单才能标记为已支付");
        }
        this.status = OrderStatus.PAID;
        this.domainEvents.add(new OrderPaidEvent(this.orderNo, paymentId));
    }

    public void cancel(String reason) {
        if (!OrderStatus.CANCELLABLE_STATUSES.contains(this.status)) {
            throw new BusinessException("当前状态不可取消");
        }
        this.status = OrderStatus.CANCELLED;
        this.domainEvents.add(new OrderCancelledEvent(this.orderNo, reason));
    }
}

下单完整链路与分布式事务

用户发起下单请求 │ ▼ OrderApplicationService.createOrder() │ ├── @GlobalTransactional ← Seata 开启全局事务(XID) │ ├── 1. 查询商品信息(productClient.getProducts) │ ├── 2. 创建订单(Order.create())→ 保存到 DB │ └── 本地事务 BEGIN │ INSERT INTO orders ... │ INSERT INTO order_items ... │ 本地事务 COMMIT │ └── Seata 记录 undo_log(后镜像) │ ├── 3. 扣减库存(inventoryClient.decreaseStock) │ └── 库存服务本地事务 │ UPDATE inventory SET stock = stock - N WHERE product_id = ? │ Seata 记录 undo_log │ ├── 4. 发起支付(paymentClient.createPayment) │ └── 支付服务本地事务 │ ├── ✅ 全部成功 → Seata TC 通知各服务提交(二阶段 COMMIT) │ 删除所有 undo_log │ └── ❌ 某步失败 → Seata TC 通知各服务回滚(二阶段 ROLLBACK) 各服务用 undo_log 生成反向 SQL 恢复数据

ApplicationService 实现

@Service
@RequiredArgsConstructor
public class OrderApplicationService {

    private final OrderRepository orderRepository;
    private final ProductClient productClient;
    private final InventoryClient inventoryClient;
    private final PaymentClient paymentClient;
    private final ApplicationEventPublisher eventPublisher;

    @GlobalTransactional  // Seata 全局事务
    public OrderDTO createOrder(CreateOrderCommand cmd) {
        // 1. 查询并验证商品
        List<ProductDTO> products = productClient.getProducts(cmd.getProductIds());
        validateProducts(products, cmd);

        // 2. 构建订单项
        List<OrderItem> items = buildOrderItems(products, cmd);

        // 3. 创建订单聚合根
        Order order = Order.create(cmd.getUserId(), items);
        orderRepository.save(order);

        // 4. 扣减库存(Seata 管理跨服务事务)
        inventoryClient.decreaseStock(
            items.stream().map(StockDecreaseItem::from).toList()
        );

        // 5. 创建支付单
        String paymentUrl = paymentClient.createPayment(
            order.getOrderNo(), order.getTotalAmount()
        );

        // 6. 发布领域事件(Seata 提交后才发布,避免事件先于数据)
        order.getDomainEvents().forEach(eventPublisher::publishEvent);

        return OrderDTO.from(order, paymentUrl);
    }
}

领域事件监听与最终一致性

@Component
@RequiredArgsConstructor
public class OrderEventHandler {

    private final RabbitTemplate rabbitTemplate;
    private final EmailService emailService;
    private final PointsService pointsService;

    // 订单创建后:发送确认邮件(异步,不影响主流程)
    @EventListener
    @Async
    public void onOrderCreated(OrderCreatedEvent event) {
        emailService.sendOrderConfirmation(event.getUserId(), event.getOrderNo());
    }

    // 订单支付后:通过 RabbitMQ 通知仓储系统发货
    @EventListener
    public void onOrderPaid(OrderPaidEvent event) {
        rabbitTemplate.convertAndSend(
            "order.events", "order.paid",
            new ShipmentCreationCommand(event.getOrderNo())
        );
        // 异步增加积分(最终一致性)
        pointsService.addPointsAsync(event.getUserId(), event.getAmount());
    }
}

项目完整目录结构

order-service/ ├── src/main/java/com/ecommerce/order/ │ │ │ ├── interfaces/ # 接口层 │ │ ├── rest/ │ │ │ └── OrderController.java │ │ ├── dto/ │ │ │ ├── CreateOrderRequest.java │ │ │ └── OrderResponse.java │ │ └── event/ │ │ └── PaymentCallbackHandler.java │ │ │ ├── application/ # 应用层 │ │ ├── service/ │ │ │ └── OrderApplicationService.java │ │ ├── command/ │ │ │ └── CreateOrderCommand.java │ │ └── event/ │ │ └── OrderEventHandler.java │ │ │ ├── domain/ # 领域层(核心,无技术依赖) │ │ ├── model/ │ │ │ ├── Order.java # 聚合根 │ │ │ ├── OrderItem.java │ │ │ ├── OrderStatus.java # 枚举 + 状态机规则 │ │ │ └── Money.java # 值对象 │ │ ├── repository/ │ │ │ └── OrderRepository.java # 接口(依赖倒置) │ │ ├── service/ │ │ │ └── OrderDomainService.java │ │ └── event/ │ │ ├── OrderCreatedEvent.java │ │ └── OrderPaidEvent.java │ │ │ └── infrastructure/ # 基础设施层 │ ├── persistence/ │ │ └── JpaOrderRepository.java # Repository 实现 │ ├── client/ │ │ ├── ProductClient.java # Feign 客户端 │ │ └── InventoryClient.java │ └── config/ │ ├── SeataConfig.java │ └── RabbitConfig.java │ └── src/main/resources/ ├── application.yml └── application-prod.yml
Tip 优先考虑业务可接受的最终一致性,而非强一致性。大多数电商场景(积分、通知、统计)都可以接受秒级到分钟级的最终一致,不必引入 Seata 等复杂的分布式事务。只有核心的金融操作(扣款+出库同时成功或同时失败)才需要强一致性保证。
Info 至此,你已掌握了 Java Spring Boot 服务端开发的完整技术栈:从 IoC/DI 基础原理,到 REST API 设计、JPA 数据访问、Security 认证授权、缓存、消息队列、微服务,直到容器化部署和 DDD 实战架构。这些技能足以支撑你构建企业级生产应用。

课程总结