本文目录导读:

我来详细解释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);
}
}
关键设计要点
- 状态不可逆:正常流转一般不允许回退(除了退款取消)
- 日志完整:每次状态变更需记录完整日志
- 事务控制:状态变更需在事务中执行
- 原子操作:状态变更和相关业务操作要一起成功或失败
- 幂等性:防止重复操作导致状态错误
这样的设计保证了订单状态的正确流转,同时便于追踪和审计。