Java订单状态案例如何流转

wen java案例 30

本文目录导读:

Java订单状态案例如何流转

  1. 订单状态枚举定义
  2. 状态流转规则定义
  3. 订单实体类
  4. 状态变更日志
  5. 订单服务实现
  6. 状态流转图(Mermaid)
  7. 使用示例
  8. 关键设计要点

我来详细解释Java订单状态流转的典型案例。

订单状态枚举定义

public enum OrderStatus {
    // 正常流转状态
    PENDING_PAYMENT(0, "待支付"),
    PENDING_SHIPMENT(1, "待发货"),
    SHIPPED(2, "已发货"),
    DELIVERED(3, "已送达"),
    COMPLETED(4, "已完成"),
    // 异常状态
    CANCELLED(-1, "已取消"),
    REFUNDING(-2, "退款中"),
    REFUNDED(-3, "已退款");
    private int code;
    private String desc;
    // 构造方法、getter方法
    OrderStatus(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }
    public int getCode() { return code; }
    public String getDesc() { return desc; }
}

状态流转规则定义

@Component
public class OrderStateMachine {
    // 定义状态流转映射
    private static final Map<OrderStatus, List<OrderStatus>> TRANSITIONS = new HashMap<>();
    static {
        // 正常正向流转
        TRANSITIONS.put(OrderStatus.PENDING_PAYMENT, Arrays.asList(
            OrderStatus.PENDING_SHIPMENT,  // 支付成功
            OrderStatus.CANCELLED          // 取消订单
        ));
        TRANSITIONS.put(OrderStatus.PENDING_SHIPMENT, Arrays.asList(
            OrderStatus.SHIPPED,           // 发货
            OrderStatus.CANCELLED          // 取消订单(未发货前)
        ));
        TRANSITIONS.put(OrderStatus.SHIPPED, Arrays.asList(
            OrderStatus.DELIVERED,         // 确认收货
            OrderStatus.REFUNDING          // 申请退款
        ));
        TRANSITIONS.put(OrderStatus.DELIVERED, Arrays.asList(
            OrderStatus.COMPLETED,         // 自动/手动完成
            OrderStatus.REFUNDING          // 申请退款
        ));
        TRANSITIONS.put(OrderStatus.COMPLETED, Arrays.asList(
            OrderStatus.REFUNDING          // 售后退款
        ));
        // 退款状态流转
        TRANSITIONS.put(OrderStatus.REFUNDING, Arrays.asList(
            OrderStatus.REFUNDED,          // 退款成功
            OrderStatus.SHIPPED            // 取消退款(恢复之前状态)
        ));
    }
    /**
     * 检查状态是否可以流转
     */
    public boolean canTransition(OrderStatus current, OrderStatus target) {
        List<OrderStatus> allowed = TRANSITIONS.get(current);
        return allowed != null && allowed.contains(target);
    }
    /**
     * 获取允许的下一个状态
     */
    public List<OrderStatus> getAllowedTransitions(OrderStatus current) {
        return TRANSITIONS.getOrDefault(current, Collections.emptyList());
    }
}

订单实体类

@Entity
@Table(name = "orders")
public class Order {
    @Id
    private Long orderId;
    @Enumerated(EnumType.STRING)
    private OrderStatus status;
    private BigDecimal totalAmount;
    private Long userId;
    private String orderNo;
    @Temporal(TemporalType.TIMESTAMP)
    private Date createTime;
    @Temporal(TemporalType.TIMESTAMP)
    private Date updateTime;
    // 状态变更记录
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderStatusLog> statusLogs;
    // getter/setter方法
}

状态变更日志

@Entity
@Table(name = "order_status_log")
public class OrderStatusLog {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToOne
    @JoinColumn(name = "order_id")
    private Order order;
    @Enumerated(EnumType.STRING)
    private OrderStatus fromStatus;
    @Enumerated(EnumType.STRING)
    private OrderStatus toStatus;
    private String operator;      // 操作人
    private String remark;        // 备注
    @Temporal(TemporalType.TIMESTAMP)
    private Date operateTime;
    // getter/setter方法
}

订单服务实现

@Service
@Slf4j
public class OrderService {
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private OrderStateMachine stateMachine;
    @Autowired
    private OrderStatusLogRepository logRepository;
    @Transactional
    public void updateOrderStatus(Long orderId, OrderStatus targetStatus, 
                                   String operator, String remark) {
        // 1. 查询订单
        Order order = orderRepository.findById(orderId)
            .orElseThrow(() -> new RuntimeException("订单不存在"));
        OrderStatus currentStatus = order.getStatus();
        // 2. 检查状态是否允许流转
        if (!stateMachine.canTransition(currentStatus, targetStatus)) {
            throw new IllegalStateException(
                String.format("不允许的状态流转: %s -> %s", 
                    currentStatus.getDesc(), targetStatus.getDesc()));
        }
        // 3. 执行状态变更
        OrderStatus previousStatus = order.getStatus();
        order.setStatus(targetStatus);
        order.setUpdateTime(new Date());
        // 4. 保存订单
        orderRepository.save(order);
        // 5. 记录状态变更日志
        OrderStatusLog log = new OrderStatusLog();
        log.setOrder(order);
        log.setFromStatus(previousStatus);
        log.setToStatus(targetStatus);
        log.setOperator(operator);
        log.setRemark(remark);
        log.setOperateTime(new Date());
        logRepository.save(log);
        log.info("订单 {} 状态变更: {} -> {}", 
            orderId, previousStatus.getDesc(), targetStatus.getDesc());
    }
    /**
     * 支付成功处理
     */
    @Transactional
    public void handlePayment(Long orderId, String operator) {
        updateOrderStatus(orderId, OrderStatus.PENDING_SHIPMENT, 
            operator, "支付成功");
        // 其他业务逻辑:发送通知、更新库存等
    }
    /**
     * 取消订单
     */
    @Transactional
    public void cancelOrder(Long orderId, String operator, String reason) {
        updateOrderStatus(orderId, OrderStatus.CANCELLED, 
            operator, "取消订单:" + reason);
        // 其他业务逻辑:退款处理、释放库存等
    }
}

状态流转图(Mermaid)

stateDiagram-v2
    [*] --> 待支付
    待支付 --> 待发货 : 支付成功
    待支付 --> 已取消 : 取消订单
    待发货 --> 已发货 : 商家发货
    待发货 --> 已取消 : 取消订单
    已发货 --> 已送达 : 确认收货
    已发货 --> 退款中 : 申请退款
    已送达 --> 已完成 : 自动/手动完成
    已送达 --> 退款中 : 申请退款
    已完成 --> 退款中 : 售后申请
    退款中 --> 已退款 : 退款成功
    退款中 --> 已发货 : 取消退款
    退款中 --> 已送达 : 取消退款

使用示例

@RestController
@RequestMapping("/api/orders")
public class OrderController {
    @Autowired
    private OrderService orderService;
    /**
     * 支付回调处理
     */
    @PostMapping("/{orderId}/pay")
    public Result<Void> handlePayment(@PathVariable Long orderId) {
        orderService.handlePayment(orderId, "系统");
        return Result.success();
    }
    /**
     * 取消订单
     */
    @PostMapping("/{orderId}/cancel")
    public Result<Void> cancelOrder(@PathVariable Long orderId, 
                                    @RequestParam String reason) {
        orderService.cancelOrder(orderId, "用户", reason);
        return Result.success();
    }
    /**
     * 查询订单状态
     */
    @GetMapping("/{orderId}/status")
    public Result<OrderStatusInfo> getStatus(@PathVariable Long orderId) {
        Order order = orderService.findOrder(orderId);
        OrderStatusInfo info = new OrderStatusInfo();
        info.setCurrentStatus(order.getStatus());
        info.setAllowedTransitions(
            stateMachine.getAllowedTransitions(order.getStatus()));
        return Result.success(info);
    }
}

关键设计要点

  1. 状态不可逆:正常流转一般不允许回退(除了退款取消)
  2. 日志完整:每次状态变更需记录完整日志
  3. 事务控制:状态变更需在事务中执行
  4. 原子操作:状态变更和相关业务操作要一起成功或失败
  5. 幂等性:防止重复操作导致状态错误

这样的设计保证了订单状态的正确流转,同时便于追踪和审计。

抱歉,评论功能暂时关闭!