电商系统设计实战用PlantUML构建购物车与订单的Java代码骨架在电商系统的开发中设计阶段往往决定了整个项目的可维护性和扩展性。我曾参与过一个中型电商平台的重构项目团队最初直接跳入编码结果在三个月后陷入了难以维护的泥潭——类之间关系混乱、职责不清每次添加新功能都像在走钢丝。后来我们引入PlantUML进行设计先行效率提升了至少40%。本文将分享如何用这个轻量级工具从购物车到订单系统构建清晰的类关系并直接生成可运行的Java代码骨架。1. 环境准备与工具链配置工欲善其事必先利其器。PlantUML虽然可以通过简单的文本描述生成UML图但高效的开发环境能大幅提升工作效率。1.1 安装PlantUML插件主流IDE都支持PlantUML插件这里以IntelliJ IDEA为例打开IDEA的插件市场Preferences Plugins搜索PlantUML并安装重启IDE后新建.puml文件即可开始绘图对于团队协作建议统一配置PlantUML渲染服务器。可以在本地搭建或使用公司内部服务器# 使用Docker快速启动PlantUML服务器 docker run -d -p 8080:8080 plantuml/plantuml-server:jetty1.2 Lombok的引入为了保持代码简洁我们使用Lombok减少样板代码。在Maven项目中添加依赖dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version1.18.24/version scopeprovided/scope /dependency提示确保团队成员IDE都安装了Lombok插件否则代码会显示编译错误2. 电商核心领域建模电商系统虽然复杂但其核心领域模型相对稳定。我们先从最基础的购物车、商品、用户开始建模。2.1 商品与库存模型商品是电商系统的核心实体其类图定义如下startuml class Product { Long id String name BigDecimal price String description ProductStatus status } class Inventory { Long id Product product Integer stock Integer locked } enum ProductStatus { AVAILABLE OUT_OF_STOCK DISCONTINUED } Product 1 -- 1 Inventory enduml对应的Java骨架代码Data AllArgsConstructor NoArgsConstructor public class Product { private Long id; private String name; private BigDecimal price; private String description; private ProductStatus status; } public enum ProductStatus { AVAILABLE, OUT_OF_STOCK, DISCONTINUED } Data public class Inventory { private Long id; private Product product; private Integer stock; private Integer locked; }2.2 用户与购物车关系用户与购物车的关系是典型的组合关系——购物车不能脱离用户独立存在startuml class User { Long userId String username String email ListCart carts } class Cart { Long cartId ListCartItem items BigDecimal totalPrice() } class CartItem { Product product Integer quantity } User 1 *-- 1..* Cart Cart 1 *-- 1..* CartItem CartItem -- Product endumlJava实现时我们使用Lombok的Builder简化对象创建Data Builder public class CartItem { private Product product; private Integer quantity; } Data public class Cart { private Long cartId; private ListCartItem items new ArrayList(); public BigDecimal totalPrice() { return items.stream() .map(item - item.getProduct().getPrice() .multiply(BigDecimal.valueOf(item.getQuantity()))) .reduce(BigDecimal.ZERO, BigDecimal::add); } } Data public class User { private Long userId; private String username; private String email; private ListCart carts new ArrayList(); }3. 订单系统的复杂关系建模订单系统涉及更多复杂关系包括聚合、组合和依赖关系。3.1 订单核心模型startuml class Order { Long orderId OrderStatus status ListOrderItem items BigDecimal totalAmount User user Payment payment Shipping shipping } class OrderItem { Product product Integer quantity BigDecimal price } enum OrderStatus { CREATED PAID SHIPPED COMPLETED CANCELLED } Order 1 *-- 1..* OrderItem Order -- User Order -- Payment Order -- Shipping OrderItem -- Product enduml对应的Java实现需要注意深拷贝问题Data public class OrderItem { private Product product; private Integer quantity; private BigDecimal price; public OrderItem(CartItem cartItem) { this.product new Product(cartItem.getProduct()); this.quantity cartItem.getQuantity(); this.price cartItem.getProduct().getPrice(); } } Data public class Order { private Long orderId; private OrderStatus status; private ListOrderItem items new ArrayList(); private BigDecimal totalAmount; private User user; private Payment payment; private Shipping shipping; public static Order fromCart(Cart cart, User user) { Order order new Order(); order.setUser(user); order.setStatus(OrderStatus.CREATED); order.setItems(cart.getItems().stream() .map(OrderItem::new) .collect(Collectors.toList())); order.setTotalAmount(cart.totalPrice()); return order; } }3.2 支付与物流的关联支付和物流通常作为独立服务存在与订单是聚合关系startuml class Payment { Long paymentId BigDecimal amount PaymentMethod method PaymentStatus status } class Shipping { Long shippingId String address ShippingMethod method ShippingStatus status } enum PaymentMethod { CREDIT_CARD PAYPAL BANK_TRANSFER } enum ShippingMethod { STANDARD EXPRESS SAME_DAY } Order o-- Payment Order o-- Shipping enduml实现时需要注意事务边界public interface PaymentService { Payment processPayment(Order order, PaymentMethod method); } Service RequiredArgsConstructor public class DefaultPaymentService implements PaymentService { private final PaymentRepository paymentRepository; Transactional public Payment processPayment(Order order, PaymentMethod method) { Payment payment Payment.builder() .amount(order.getTotalAmount()) .method(method) .status(PaymentStatus.PENDING) .build(); return paymentRepository.save(payment); } }4. 高级建模技巧与团队协作4.1 处理多对多关系商品分类是典型的多对多关系我们需要引入关联类startuml class Product { Long id String name } class Category { Long id String name } class ProductCategory { Product product Category category Integer displayOrder } Product 1 -- * ProductCategory Category 1 -- * ProductCategory endumlJPA实现示例Entity Data public class ProductCategory { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; ManyToOne private Product product; ManyToOne private Category category; private Integer displayOrder; }4.2 版本控制与文档化PlantUML文件应该与代码一起纳入版本控制。建议的目录结构src/ main/ java/ resources/ diagrams/ product.puml order.puml payment.puml在团队协作中可以配置CI流程自动生成UML图并发布到内部文档站点。以下是一个GitLab CI示例generate_diagrams: image: plantuml/plantuml script: - plantuml -tsvg src/main/resources/diagrams/*.puml artifacts: paths: - src/main/resources/diagrams/*.svg注意确保团队成员遵循统一的命名规范如使用camelCase命名关系角色5. 从设计到实现的完整流程让我们通过一个完整场景串联所有概念用户将商品加入购物车并创建订单。5.1 购物车操作序列startuml actor User participant CartController as CC participant CartService as CS participant ProductService as PS User - CC : 添加商品(id123, quantity2) CC - CS : addItem(userId, productId, quantity) CS - PS : getProduct(productId) PS -- CS : Product CS -- CC : Cart CC -- User : 更新后的购物车 enduml对应的服务层实现Service RequiredArgsConstructor public class CartServiceImpl implements CartService { private final CartRepository cartRepository; private final ProductService productService; Transactional public Cart addItem(Long userId, Long productId, int quantity) { Product product productService.getProduct(productId); Cart cart cartRepository.findByUserId(userId) .orElseGet(() - createNewCart(userId)); cart.getItems().stream() .filter(item - item.getProduct().getId().equals(productId)) .findFirst() .ifPresentOrElse( item - item.setQuantity(item.getQuantity() quantity), () - cart.getItems().add( CartItem.builder() .product(product) .quantity(quantity) .build() ) ); return cartRepository.save(cart); } }5.2 下单流程的关键设计下单过程涉及多个聚合根的修改需要考虑分布式事务startuml actor User participant OrderController as OC participant OrderService as OS participant InventoryService as IS participant PaymentService as PYS User - OC : 创建订单(cartId) OC - OS : createOrder(userId, cartId) OS - IS : 锁定库存(cartItems) IS -- OS : 成功/失败 OS - PYS : 创建支付订单 PYS -- OS : Payment OS -- OC : Order OC -- User : 订单详情 enduml使用Saga模式处理分布式事务public class OrderCreationSaga { private final InventoryService inventoryService; private final PaymentService paymentService; private final OrderRepository orderRepository; Transactional public Order createOrder(Long userId, Long cartId) { // 1. 获取购物车 Cart cart cartService.getCart(cartId); // 2. 锁定库存 try { inventoryService.lockInventory(cart.getItems()); } catch (InventoryException e) { throw new OrderException(库存不足); } // 3. 创建订单 Order order Order.fromCart(cart, user); order orderRepository.save(order); // 4. 创建支付 try { Payment payment paymentService.createPayment(order); order.setPayment(payment); } catch (PaymentException e) { inventoryService.unlockInventory(cart.getItems()); throw new OrderException(支付创建失败); } return orderRepository.save(order); } }在实际项目中我们发现将PlantUML图作为代码审查的一部分能显著提高设计质量。团队约定每个Pull Request必须包含相关的UML图更新这帮助我们早期发现了很多设计缺陷。
从购物车到订单系统:一个真实业务场景,手把手教你用PlantUML画类图并生成Java代码骨架
电商系统设计实战用PlantUML构建购物车与订单的Java代码骨架在电商系统的开发中设计阶段往往决定了整个项目的可维护性和扩展性。我曾参与过一个中型电商平台的重构项目团队最初直接跳入编码结果在三个月后陷入了难以维护的泥潭——类之间关系混乱、职责不清每次添加新功能都像在走钢丝。后来我们引入PlantUML进行设计先行效率提升了至少40%。本文将分享如何用这个轻量级工具从购物车到订单系统构建清晰的类关系并直接生成可运行的Java代码骨架。1. 环境准备与工具链配置工欲善其事必先利其器。PlantUML虽然可以通过简单的文本描述生成UML图但高效的开发环境能大幅提升工作效率。1.1 安装PlantUML插件主流IDE都支持PlantUML插件这里以IntelliJ IDEA为例打开IDEA的插件市场Preferences Plugins搜索PlantUML并安装重启IDE后新建.puml文件即可开始绘图对于团队协作建议统一配置PlantUML渲染服务器。可以在本地搭建或使用公司内部服务器# 使用Docker快速启动PlantUML服务器 docker run -d -p 8080:8080 plantuml/plantuml-server:jetty1.2 Lombok的引入为了保持代码简洁我们使用Lombok减少样板代码。在Maven项目中添加依赖dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version1.18.24/version scopeprovided/scope /dependency提示确保团队成员IDE都安装了Lombok插件否则代码会显示编译错误2. 电商核心领域建模电商系统虽然复杂但其核心领域模型相对稳定。我们先从最基础的购物车、商品、用户开始建模。2.1 商品与库存模型商品是电商系统的核心实体其类图定义如下startuml class Product { Long id String name BigDecimal price String description ProductStatus status } class Inventory { Long id Product product Integer stock Integer locked } enum ProductStatus { AVAILABLE OUT_OF_STOCK DISCONTINUED } Product 1 -- 1 Inventory enduml对应的Java骨架代码Data AllArgsConstructor NoArgsConstructor public class Product { private Long id; private String name; private BigDecimal price; private String description; private ProductStatus status; } public enum ProductStatus { AVAILABLE, OUT_OF_STOCK, DISCONTINUED } Data public class Inventory { private Long id; private Product product; private Integer stock; private Integer locked; }2.2 用户与购物车关系用户与购物车的关系是典型的组合关系——购物车不能脱离用户独立存在startuml class User { Long userId String username String email ListCart carts } class Cart { Long cartId ListCartItem items BigDecimal totalPrice() } class CartItem { Product product Integer quantity } User 1 *-- 1..* Cart Cart 1 *-- 1..* CartItem CartItem -- Product endumlJava实现时我们使用Lombok的Builder简化对象创建Data Builder public class CartItem { private Product product; private Integer quantity; } Data public class Cart { private Long cartId; private ListCartItem items new ArrayList(); public BigDecimal totalPrice() { return items.stream() .map(item - item.getProduct().getPrice() .multiply(BigDecimal.valueOf(item.getQuantity()))) .reduce(BigDecimal.ZERO, BigDecimal::add); } } Data public class User { private Long userId; private String username; private String email; private ListCart carts new ArrayList(); }3. 订单系统的复杂关系建模订单系统涉及更多复杂关系包括聚合、组合和依赖关系。3.1 订单核心模型startuml class Order { Long orderId OrderStatus status ListOrderItem items BigDecimal totalAmount User user Payment payment Shipping shipping } class OrderItem { Product product Integer quantity BigDecimal price } enum OrderStatus { CREATED PAID SHIPPED COMPLETED CANCELLED } Order 1 *-- 1..* OrderItem Order -- User Order -- Payment Order -- Shipping OrderItem -- Product enduml对应的Java实现需要注意深拷贝问题Data public class OrderItem { private Product product; private Integer quantity; private BigDecimal price; public OrderItem(CartItem cartItem) { this.product new Product(cartItem.getProduct()); this.quantity cartItem.getQuantity(); this.price cartItem.getProduct().getPrice(); } } Data public class Order { private Long orderId; private OrderStatus status; private ListOrderItem items new ArrayList(); private BigDecimal totalAmount; private User user; private Payment payment; private Shipping shipping; public static Order fromCart(Cart cart, User user) { Order order new Order(); order.setUser(user); order.setStatus(OrderStatus.CREATED); order.setItems(cart.getItems().stream() .map(OrderItem::new) .collect(Collectors.toList())); order.setTotalAmount(cart.totalPrice()); return order; } }3.2 支付与物流的关联支付和物流通常作为独立服务存在与订单是聚合关系startuml class Payment { Long paymentId BigDecimal amount PaymentMethod method PaymentStatus status } class Shipping { Long shippingId String address ShippingMethod method ShippingStatus status } enum PaymentMethod { CREDIT_CARD PAYPAL BANK_TRANSFER } enum ShippingMethod { STANDARD EXPRESS SAME_DAY } Order o-- Payment Order o-- Shipping enduml实现时需要注意事务边界public interface PaymentService { Payment processPayment(Order order, PaymentMethod method); } Service RequiredArgsConstructor public class DefaultPaymentService implements PaymentService { private final PaymentRepository paymentRepository; Transactional public Payment processPayment(Order order, PaymentMethod method) { Payment payment Payment.builder() .amount(order.getTotalAmount()) .method(method) .status(PaymentStatus.PENDING) .build(); return paymentRepository.save(payment); } }4. 高级建模技巧与团队协作4.1 处理多对多关系商品分类是典型的多对多关系我们需要引入关联类startuml class Product { Long id String name } class Category { Long id String name } class ProductCategory { Product product Category category Integer displayOrder } Product 1 -- * ProductCategory Category 1 -- * ProductCategory endumlJPA实现示例Entity Data public class ProductCategory { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; ManyToOne private Product product; ManyToOne private Category category; private Integer displayOrder; }4.2 版本控制与文档化PlantUML文件应该与代码一起纳入版本控制。建议的目录结构src/ main/ java/ resources/ diagrams/ product.puml order.puml payment.puml在团队协作中可以配置CI流程自动生成UML图并发布到内部文档站点。以下是一个GitLab CI示例generate_diagrams: image: plantuml/plantuml script: - plantuml -tsvg src/main/resources/diagrams/*.puml artifacts: paths: - src/main/resources/diagrams/*.svg注意确保团队成员遵循统一的命名规范如使用camelCase命名关系角色5. 从设计到实现的完整流程让我们通过一个完整场景串联所有概念用户将商品加入购物车并创建订单。5.1 购物车操作序列startuml actor User participant CartController as CC participant CartService as CS participant ProductService as PS User - CC : 添加商品(id123, quantity2) CC - CS : addItem(userId, productId, quantity) CS - PS : getProduct(productId) PS -- CS : Product CS -- CC : Cart CC -- User : 更新后的购物车 enduml对应的服务层实现Service RequiredArgsConstructor public class CartServiceImpl implements CartService { private final CartRepository cartRepository; private final ProductService productService; Transactional public Cart addItem(Long userId, Long productId, int quantity) { Product product productService.getProduct(productId); Cart cart cartRepository.findByUserId(userId) .orElseGet(() - createNewCart(userId)); cart.getItems().stream() .filter(item - item.getProduct().getId().equals(productId)) .findFirst() .ifPresentOrElse( item - item.setQuantity(item.getQuantity() quantity), () - cart.getItems().add( CartItem.builder() .product(product) .quantity(quantity) .build() ) ); return cartRepository.save(cart); } }5.2 下单流程的关键设计下单过程涉及多个聚合根的修改需要考虑分布式事务startuml actor User participant OrderController as OC participant OrderService as OS participant InventoryService as IS participant PaymentService as PYS User - OC : 创建订单(cartId) OC - OS : createOrder(userId, cartId) OS - IS : 锁定库存(cartItems) IS -- OS : 成功/失败 OS - PYS : 创建支付订单 PYS -- OS : Payment OS -- OC : Order OC -- User : 订单详情 enduml使用Saga模式处理分布式事务public class OrderCreationSaga { private final InventoryService inventoryService; private final PaymentService paymentService; private final OrderRepository orderRepository; Transactional public Order createOrder(Long userId, Long cartId) { // 1. 获取购物车 Cart cart cartService.getCart(cartId); // 2. 锁定库存 try { inventoryService.lockInventory(cart.getItems()); } catch (InventoryException e) { throw new OrderException(库存不足); } // 3. 创建订单 Order order Order.fromCart(cart, user); order orderRepository.save(order); // 4. 创建支付 try { Payment payment paymentService.createPayment(order); order.setPayment(payment); } catch (PaymentException e) { inventoryService.unlockInventory(cart.getItems()); throw new OrderException(支付创建失败); } return orderRepository.save(order); } }在实际项目中我们发现将PlantUML图作为代码审查的一部分能显著提高设计质量。团队约定每个Pull Request必须包含相关的UML图更新这帮助我们早期发现了很多设计缺陷。