状态机是软件开发中处理复杂业务流程的核心模式之一。本文将深入探讨Java中的状态机实现,从基础概念到高级应用,为你打造完整的状态机开发指南。

🎯 状态机基础概念

1. 状态机是什么?

🏗️ 状态机定义

1
2
3
4
5
6
7
8
9
状态机(State Machine)是一个数学模型,由以下核心组件组成:

1. **状态(State)**:对象在某个时刻的条件或状况
2. **事件(Event)**:触发状态转换的外部输入
3. **转换(Transition)**:从一个状态到另一个状态的变化过程
4. **动作(Action)**:状态转换时执行的操作
5. **守卫条件(Guard)**:控制转换是否可以发生的条件

状态机 = 状态集合 + 事件集合 + 转换规则 + 初始状态

📊 状态机图解

1
2
3
4
5
6
7
8
9
10
11
stateDiagram-v2
[*] --> Draft: 创建订单
Draft --> Pending: 提交订单
Pending --> Paid: 支付成功
Pending --> Cancelled: 取消订单
Paid --> Shipped: 发货
Paid --> Refunded: 申请退款
Shipped --> Delivered: 确认收货
Delivered --> [*]
Cancelled --> [*]
Refunded --> [*]

2. 状态机分类

🎨 确定性有限自动机(DFA)

  • 特点:每个状态对每个输入都有唯一的后继状态
  • 优点:简单、确定性强、易于理解
  • 缺点:灵活性差,无法处理复杂业务逻辑

🔄 非确定性有限自动机(NFA)

  • 特点:一个状态对一个输入可以有多个后继状态
  • 优点:灵活性强,可以处理复杂的业务场景
  • 缺点:实现复杂,难以调试

🤖 层次状态机(Hierarchical State Machine)

  • 特点:支持状态嵌套,父状态包含子状态
  • 优点:可以简化复杂状态图,提高可维护性
  • 缺点:设计复杂度较高

🏗️ Java状态机实现方式

1. 枚举实现简单状态机

🎯 基础枚举状态机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// 订单状态枚举
public enum OrderState {
DRAFT("草稿") {
@Override
public OrderState next(OrderEvent event) {
return switch (event) {
case SUBMIT -> PENDING;
case CANCEL -> CANCELLED;
default -> this;
};
}
},
PENDING("待支付") {
@Override
public OrderState next(OrderEvent event) {
return switch (event) {
case PAY -> PAID;
case CANCEL -> CANCELLED;
case TIMEOUT -> CANCELLED;
default -> this;
};
}
},
PAID("已支付") {
@Override
public OrderState next(OrderEvent event) {
return switch (event) {
case SHIP -> SHIPPED;
case REFUND -> REFUNDED;
default -> this;
};
}
},
SHIPPED("已发货") {
@Override
public OrderState next(OrderEvent event) {
return switch (event) {
case DELIVER -> DELIVERED;
default -> this;
};
}
},
DELIVERED("已送达"),
CANCELLED("已取消"),
REFUNDED("已退款");

private final String description;

OrderState(String description) {
this.description = description;
}

// 默认实现,返回当前状态
public OrderState next(OrderEvent event) {
return this;
}

public String getDescription() {
return description;
}
}

// 订单事件枚举
public enum OrderEvent {
SUBMIT, // 提交订单
PAY, // 支付
CANCEL, // 取消
TIMEOUT, // 超时
SHIP, // 发货
DELIVER, // 送达
REFUND // 退款
}

🚀 枚举状态机使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@Service
@Slf4j
public class OrderService {

public Order processOrderEvent(Long orderId, OrderEvent event) {
Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new RuntimeException("订单不存在"));

OrderState currentState = order.getState();
OrderState nextState = currentState.next(event);

// 检查状态是否发生变化
if (currentState != nextState) {
log.info("订单 {} 状态从 {} 变更为 {}", orderId, currentState, nextState);

// 执行状态转换逻辑
executeStateTransition(order, currentState, nextState, event);

// 更新订单状态
order.setState(nextState);
order.setUpdatedAt(LocalDateTime.now());
orderRepository.save(order);

// 发布状态变更事件
eventPublisher.publishEvent(new OrderStateChangedEvent(order, currentState, nextState, event));
}

return order;
}

private void executeStateTransition(Order order, OrderState from, OrderState to, OrderEvent event) {
switch (to) {
case PAID:
// 处理支付成功逻辑
paymentService.confirmPayment(order);
break;
case SHIPPED:
// 处理发货逻辑
shippingService.createShipment(order);
break;
case CANCELLED:
// 处理取消逻辑
inventoryService.releaseStock(order);
break;
case REFUNDED:
// 处理退款逻辑
refundService.processRefund(order);
break;
}
}
}

2. 状态模式实现状态机

🎨 状态模式设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// 状态接口
public interface OrderState {
void handle(Order order, OrderEvent event);
OrderStateEnum getState();
}

// 待支付状态
@Component
public class PendingState implements OrderState {

@Autowired
private PaymentService paymentService;

@Override
public void handle(Order order, OrderEvent event) {
switch (event) {
case PAY:
// 执行支付逻辑
if (paymentService.processPayment(order)) {
order.setState(new PaidState());
log.info("订单 {} 支付成功", order.getId());
} else {
throw new PaymentException("支付失败");
}
break;
case CANCEL:
order.setState(new CancelledState());
log.info("订单 {} 已取消", order.getId());
break;
default:
throw new InvalidEventException("无效事件: " + event);
}
}

@Override
public OrderStateEnum getState() {
return OrderStateEnum.PENDING;
}
}

// 已支付状态
@Component
public class PaidState implements OrderState {

@Autowired
private ShippingService shippingService;

@Override
public void handle(Order order, OrderEvent event) {
switch (event) {
case SHIP:
shippingService.createShipment(order);
order.setState(new ShippedState());
log.info("订单 {} 已发货", order.getId());
break;
case REFUND:
order.setState(new RefundedState());
log.info("订单 {} 正在退款", order.getId());
break;
default:
throw new InvalidEventException("无效事件: " + event);
}
}

@Override
public OrderStateEnum getState() {
return OrderStateEnum.PAID;
}
}

🎯 状态机上下文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@Service
@Slf4j
public class OrderStateMachine {

private final Map<OrderStateEnum, OrderState> stateMap;

@Autowired
public OrderStateMachine(List<OrderState> states) {
this.stateMap = states.stream()
.collect(Collectors.toMap(OrderState::getState, Function.identity()));
}

public void processEvent(Order order, OrderEvent event) {
OrderState currentState = stateMap.get(order.getState());
if (currentState == null) {
throw new IllegalStateException("未知状态: " + order.getState());
}

log.info("订单 {} 当前状态: {}, 处理事件: {}",
order.getId(), currentState.getState(), event);

try {
currentState.handle(order, event);
} catch (Exception e) {
log.error("处理订单事件失败: orderId={}, event={}, error={}",
order.getId(), event, e.getMessage());
throw e;
}
}

// 批量处理事件
@Async
public void processEvents(List<OrderEventRequest> requests) {
for (OrderEventRequest request : requests) {
try {
Order order = orderRepository.findById(request.getOrderId())
.orElseThrow(() -> new OrderNotFoundException(request.getOrderId()));

processEvent(order, request.getEvent());
orderRepository.save(order);

} catch (Exception e) {
log.error("批量处理事件失败: {}", request, e);
// 记录失败事件,稍后重试
failedEventRepository.save(new FailedEvent(request, e));
}
}
}
}

3. Spring State Machine实现

🌟 Spring State Machine配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderState, OrderEvent> {

@Override
public void configure(StateMachineStateConfigurer<OrderState, OrderEvent> states) throws Exception {
states
.withStates()
.initial(OrderState.DRAFT)
.state(OrderState.PENDING)
.state(OrderState.PAID)
.state(OrderState.SHIPPED)
.state(OrderState.DELIVERED)
.end(OrderState.CANCELLED)
.end(OrderState.REFUNDED);
}

@Override
public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception {
transitions
.withExternal()
.source(OrderState.DRAFT).target(OrderState.PENDING)
.event(OrderEvent.SUBMIT)
.action(orderSubmitAction())
.and()
.withExternal()
.source(OrderState.PENDING).target(OrderState.PAID)
.event(OrderEvent.PAY)
.action(orderPayAction())
.guard(orderPayGuard())
.and()
.withExternal()
.source(OrderState.PENDING).target(OrderState.CANCELLED)
.event(OrderEvent.CANCEL)
.action(orderCancelAction())
.and()
.withExternal()
.source(OrderState.PAID).target(OrderState.SHIPPED)
.event(OrderEvent.SHIP)
.action(orderShipAction())
.and()
.withExternal()
.source(OrderState.SHIPPED).target(OrderState.DELIVERED)
.event(OrderEvent.DELIVER)
.action(orderDeliverAction());
}

@Bean
public Action<OrderState, OrderEvent> orderSubmitAction() {
return context -> {
Order order = (Order) context.getMessageHeader("order");
log.info("订单 {} 已提交", order.getId());
// 执行提交逻辑
order.setSubmittedAt(LocalDateTime.now());
};
}

@Bean
public Action<OrderState, OrderEvent> orderPayAction() {
return context -> {
Order order = (Order) context.getMessageHeader("order");
log.info("订单 {} 支付成功", order.getId());
// 执行支付逻辑
paymentService.confirmPayment(order);
};
}

@Bean
public Guard<OrderState, OrderEvent> orderPayGuard() {
return context -> {
Order order = (Order) context.getMessageHeader("order");
// 检查支付金额是否正确
return paymentService.validatePayment(order);
};
}
}

🎯 Spring State Machine使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@Service
@Slf4j
public class OrderStateMachineService {

@Autowired
private StateMachine<OrderState, OrderEvent> stateMachine;

@Autowired
private OrderRepository orderRepository;

public void processOrderEvent(Long orderId, OrderEvent event) {
Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new RuntimeException("订单不存在"));

// 启动状态机
stateMachine.start();

try {
// 设置当前状态
stateMachine.getStateMachineAccessor()
.doWithAllRegions(access -> access.resetStateMachine(
new DefaultStateMachineContext<>(order.getState(), null, null, null)));

// 发送事件
Message<OrderEvent> message = MessageBuilder
.withPayload(event)
.setHeader("order", order)
.build();

boolean success = stateMachine.sendEvent(message);

if (success) {
// 获取新状态并更新订单
OrderState newState = stateMachine.getState().getId();
order.setState(newState);
order.setUpdatedAt(LocalDateTime.now());
orderRepository.save(order);

log.info("订单 {} 状态从 {} 变更为 {}",
orderId, order.getState(), newState);
} else {
throw new StateMachineException("状态转换失败");
}

} finally {
// 停止状态机
stateMachine.stop();
}
}

// 监听状态变化
@OnStateChanged
public void onStateChanged(State<OrderState, OrderEvent> from, State<OrderState, OrderEvent> to) {
log.info("状态从 {} 变更为 {}", from.getId(), to.getId());
}

// 监听转换事件
@OnTransition
public void onTransition(Transition<OrderState, OrderEvent> transition) {
log.info("转换: {} -> {} via {}",
transition.getSource().getId(),
transition.getTarget().getId(),
transition.getTrigger().getEvent());
}
}

⚖️ 状态机的优缺点分析

1. 状态机的优点

✅ 代码结构清晰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 传统if-else处理(难以维护)
public void processOrder(Order order, String action) {
if ("submit".equals(action)) {
if (order.getState() == OrderState.DRAFT) {
// 提交逻辑
order.setState(OrderState.PENDING);
}
} else if ("pay".equals(action)) {
if (order.getState() == OrderState.PENDING) {
// 支付逻辑
order.setState(OrderState.PAID);
}
} // ... 更多if-else
}

// 状态机处理(结构清晰)
stateMachine.processEvent(order, OrderEvent.valueOf(action.toUpperCase()));

✅ 业务逻辑集中

  • 状态转换规则集中管理:所有状态转换逻辑在一个地方定义
  • 转换动作统一处理:状态转换时的业务逻辑统一管理
  • 状态变更历史可追踪:可以记录状态变迁历史

✅ 易于扩展

  • 新增状态简单:只需要添加新的状态类或枚举值
  • 新增事件简单:添加新事件及其处理逻辑
  • 修改转换规则简单:集中修改转换配置

✅ 错误处理完善

  • 无效转换检测:自动检测无效的状态转换
  • 异常处理统一:统一的异常处理机制
  • 回滚机制:支持状态转换失败时的回滚

2. 状态机的缺点

❌ 学习成本较高

  • 概念理解复杂:需要理解状态机理论
  • 框架学习曲线陡峭:Spring State Machine等框架有一定的学习成本
  • 调试困难:状态机调试相对复杂

❌ 性能开销

  • 对象创建开销:状态对象创建和销毁的开销
  • 状态持久化开销:状态需要持久化存储
  • 序列化开销:分布式环境下状态序列化开销

❌ 适用场景有限

  • 不适合简单状态管理:对于简单的状态管理,使用状态机可能过于复杂
  • 不适合高并发场景:状态机可能成为性能瓶颈
  • 不适合无状态业务:纯函数式业务不需要状态机

🚀 事件触发机制详解

1. 同步事件触发

⚡ 直接方法调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Service
public class OrderService {

@Autowired
private OrderStateMachine stateMachine;

// 同步触发事件
public void submitOrder(Long orderId) {
Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException(orderId));

// 直接触发事件
stateMachine.processEvent(order, OrderEvent.SUBMIT);

// 事件处理完成后继续执行
sendNotification(order);
}
}

🔄 事务中触发事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Service
@Transactional
public class OrderService {

public void payOrder(Long orderId, PaymentInfo paymentInfo) {
Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException(orderId));

// 验证支付信息
paymentService.validatePayment(paymentInfo);

// 在事务中触发状态转换
stateMachine.processEvent(order, OrderEvent.PAY);

// 如果状态转换失败,事务会回滚
orderRepository.save(order);

// 发送通知
notificationService.sendPaymentSuccessNotification(order);
}
}

2. 异步事件触发

📨 消息队列触发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@Service
@Slf4j
public class OrderEventProcessor {

@Autowired
private OrderStateMachine stateMachine;

@Autowired
private OrderEventPublisher eventPublisher;

// 异步处理事件
@Async
public void processEventAsync(Long orderId, OrderEvent event) {
try {
Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException(orderId));

log.info("异步处理订单事件: orderId={}, event={}", orderId, event);

stateMachine.processEvent(order, event);
orderRepository.save(order);

// 发布状态变更事件
eventPublisher.publishOrderStateChangedEvent(order, event);

} catch (Exception e) {
log.error("异步处理订单事件失败: orderId={}, event={}", orderId, event, e);
// 重新发布事件到重试队列
eventPublisher.publishToRetryQueue(orderId, event);
}
}

// 批量异步处理
@Async
public void processEventsBatch(List<OrderEventRequest> requests) {
log.info("开始批量处理 {} 个订单事件", requests.size());

List<CompletableFuture<Void>> futures = requests.stream()
.map(request -> CompletableFuture.runAsync(() ->
processEventAsync(request.getOrderId(), request.getEvent())))
.collect(Collectors.toList());

// 等待所有事件处理完成
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.whenComplete((result, throwable) -> {
if (throwable != null) {
log.error("批量处理事件时发生错误", throwable);
} else {
log.info("批量处理 {} 个订单事件完成", requests.size());
}
});
}
}

📬 事件驱动架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@Service
@Slf4j
public class OrderEventListener {

@Autowired
private OrderStateMachine stateMachine;

// 监听支付成功事件
@EventListener
public void onPaymentSuccess(PaymentSuccessEvent event) {
log.info("收到支付成功事件: {}", event.getOrderId());

try {
Order order = orderRepository.findById(event.getOrderId())
.orElseThrow(() -> new OrderNotFoundException(event.getOrderId()));

// 触发状态转换
stateMachine.processEvent(order, OrderEvent.PAY);
orderRepository.save(order);

} catch (Exception e) {
log.error("处理支付成功事件失败: {}", event.getOrderId(), e);
}
}

// 监听发货完成事件
@EventListener
public void onShipmentDelivered(ShipmentDeliveredEvent event) {
log.info("收到发货完成事件: {}", event.getOrderId());

Order order = orderRepository.findById(event.getOrderId())
.orElseThrow(() -> new OrderNotFoundException(event.getOrderId()));

stateMachine.processEvent(order, OrderEvent.DELIVER);
orderRepository.save(order);
}

// 监听超时事件
@Scheduled(fixedRate = 60000) // 每分钟检查一次
public void checkTimeoutOrders() {
List<Order> timeoutOrders = orderRepository.findTimeoutOrders(
LocalDateTime.now().minusMinutes(30));

for (Order order : timeoutOrders) {
try {
log.info("处理超时订单: {}", order.getId());
stateMachine.processEvent(order, OrderEvent.TIMEOUT);
orderRepository.save(order);
} catch (Exception e) {
log.error("处理超时订单失败: {}", order.getId(), e);
}
}
}
}

3. 事件触发策略

🎯 事件去重机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@Service
@Slf4j
public class EventDeduplicationService {

@Autowired
private RedisTemplate<String, String> redisTemplate;

private static final String EVENT_KEY_PREFIX = "order:event:";
private static final Duration EVENT_TTL = Duration.ofHours(24);

public boolean isEventProcessed(String eventId) {
String key = EVENT_KEY_PREFIX + eventId;
return Boolean.TRUE.equals(redisTemplate.hasKey(key));
}

public void markEventProcessed(String eventId) {
String key = EVENT_KEY_PREFIX + eventId;
redisTemplate.opsForValue().set(key, "processed", EVENT_TTL);
}

public boolean processEventIfNotDuplicate(String eventId, Runnable eventProcessor) {
if (isEventProcessed(eventId)) {
log.warn("事件已处理,跳过: {}", eventId);
return false;
}

try {
eventProcessor.run();
markEventProcessed(eventId);
return true;
} catch (Exception e) {
log.error("事件处理失败: {}", eventId, e);
// 处理失败时不标记为已处理,允许重试
return false;
}
}
}

🔄 事件重试机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@Service
@Slf4j
public class EventRetryService {

@Autowired
private OrderStateMachine stateMachine;

private static final int MAX_RETRY_ATTEMPTS = 3;
private static final Duration RETRY_DELAY = Duration.ofSeconds(30);

@Async
public void processEventWithRetry(Long orderId, OrderEvent event, int attempt) {
try {
log.info("尝试处理事件 (第{}次): orderId={}, event={}",
attempt, orderId, event);

Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException(orderId));

stateMachine.processEvent(order, event);
orderRepository.save(order);

log.info("事件处理成功: orderId={}, event={}", orderId, event);

} catch (Exception e) {
log.error("事件处理失败 (第{}次): orderId={}, event={}",
attempt, orderId, event, e);

if (attempt < MAX_RETRY_ATTEMPTS) {
// 延迟重试
scheduleRetry(orderId, event, attempt + 1);
} else {
// 达到最大重试次数,发送告警
alertService.sendAlert("事件处理失败", String.format(
"订单 %d 事件 %s 处理失败,已达到最大重试次数", orderId, event));
}
}
}

@Async
public void scheduleRetry(Long orderId, OrderEvent event, int attempt) {
try {
Thread.sleep(RETRY_DELAY.toMillis());
processEventWithRetry(orderId, event, attempt);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("重试调度被中断: orderId={}, event={}", orderId, event);
}
}
}

🏭 实际应用案例

1. 订单流程管理

📋 电商订单状态机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public enum OrderState {
DRAFT, // 草稿
PENDING_PAYMENT, // 待支付
PAID, // 已支付
PROCESSING, // 处理中
SHIPPED, // 已发货
DELIVERED, // 已送达
CANCELLED, // 已取消
REFUNDED, // 已退款
CLOSED // 已关闭
}

public enum OrderEvent {
CREATE, // 创建订单
PAY, // 支付
CONFIRM, // 确认订单
SHIP, // 发货
DELIVER, // 确认收货
CANCEL, // 取消订单
REFUND_REQUEST, // 申请退款
REFUND_APPROVE, // 退款审核通过
REFUND_REJECT, // 退款审核拒绝
CLOSE // 关闭订单
}

🔄 订单状态机实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderState, OrderEvent> {

@Override
public void configure(StateMachineStateConfigurer<OrderState, OrderEvent> states) throws Exception {
states
.withStates()
.initial(OrderState.DRAFT)
.state(OrderState.PENDING_PAYMENT)
.state(OrderState.PAID)
.state(OrderState.PROCESSING)
.state(OrderState.SHIPPED)
.state(OrderState.DELIVERED)
.end(OrderState.CANCELLED)
.end(OrderState.REFUNDED)
.end(OrderState.CLOSED);
}

@Override
public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception {
transitions
// 创建订单
.withExternal()
.source(OrderState.DRAFT).target(OrderState.PENDING_PAYMENT)
.event(OrderEvent.CREATE)
.action(createOrderAction())
.and()
// 支付订单
.withExternal()
.source(OrderState.PENDING_PAYMENT).target(OrderState.PAID)
.event(OrderEvent.PAY)
.action(payOrderAction())
.guard(paymentGuard())
.and()
// 确认订单
.withExternal()
.source(OrderState.PAID).target(OrderState.PROCESSING)
.event(OrderEvent.CONFIRM)
.action(confirmOrderAction())
.and()
// 发货
.withExternal()
.source(OrderState.PROCESSING).target(OrderState.SHIPPED)
.event(OrderEvent.SHIP)
.action(shipOrderAction())
.and()
// 确认收货
.withExternal()
.source(OrderState.SHIPPED).target(OrderState.DELIVERED)
.event(OrderEvent.DELIVER)
.action(deliverOrderAction())
.and()
// 取消订单(从多个状态都可以取消)
.withExternal()
.source(OrderState.DRAFT).target(OrderState.CANCELLED)
.event(OrderEvent.CANCEL)
.action(cancelOrderAction())
.and()
.withExternal()
.source(OrderState.PENDING_PAYMENT).target(OrderState.CANCELLED)
.event(OrderEvent.CANCEL)
.action(cancelOrderAction())
.and()
// 退款流程
.withExternal()
.source(OrderState.PAID).target(OrderState.REFUNDED)
.event(OrderEvent.REFUND_REQUEST)
.action(refundRequestAction())
.guard(refundGuard())
.and()
.withExternal()
.source(OrderState.DELIVERED).target(OrderState.REFUNDED)
.event(OrderEvent.REFUND_REQUEST)
.action(refundRequestAction())
.guard(refundGuard());
}

@Bean
public Action<OrderState, OrderEvent> createOrderAction() {
return context -> {
Order order = context.getMessage().getHeaders().get("order", Order.class);
order.setCreatedAt(LocalDateTime.now());
orderRepository.save(order);
log.info("订单 {} 创建成功", order.getId());
};
}

@Bean
public Guard<OrderState, OrderEvent> paymentGuard() {
return context -> {
Order order = context.getMessage().getHeaders().get("order", Order.class);
// 检查支付金额是否正确
BigDecimal paidAmount = context.getMessage().getHeaders().get("paidAmount", BigDecimal.class);
return order.getTotalAmount().compareTo(paidAmount) == 0;
};
}
}

2. 用户认证流程

🔐 用户认证状态机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public enum UserAuthState {
UNREGISTERED, // 未注册
REGISTERED, // 已注册
EMAIL_VERIFIED, // 邮箱已验证
PHONE_VERIFIED, // 手机号已验证
ACTIVE, // 激活状态
SUSPENDED, // 暂停状态
LOCKED, // 锁定状态
DELETED // 已删除
}

public enum UserAuthEvent {
REGISTER, // 注册
VERIFY_EMAIL, // 验证邮箱
VERIFY_PHONE, // 验证手机号
ACTIVATE, // 激活账户
LOGIN_SUCCESS, // 登录成功
LOGIN_FAILED, // 登录失败
PASSWORD_RESET, // 重置密码
SUSPEND, // 暂停账户
LOCK, // 锁定账户
DELETE // 删除账户
}

3. 审批工作流

📝 审批流程状态机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public enum ApprovalState {
DRAFT, // 草稿
PENDING_REVIEW, // 待审核
UNDER_REVIEW, // 审核中
APPROVED, // 已批准
REJECTED, // 已拒绝
REVISION_NEEDED, // 需要修改
CANCELLED // 已取消
}

public enum ApprovalEvent {
SUBMIT, // 提交审核
ASSIGN_REVIEWER, // 分配审核人
START_REVIEW, // 开始审核
APPROVE, // 批准
REJECT, // 拒绝
REQUEST_REVISION,// 请求修改
REVISE, // 修改
CANCEL // 取消
}

🎯 状态机最佳实践

1. 设计原则

🏗️ 单一职责原则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 每个状态类只负责自己的转换逻辑
public class PaidState implements OrderState {
@Override
public void handle(Order order, OrderEvent event) {
// 只处理已支付状态的转换逻辑
switch (event) {
case SHIP:
shipOrder(order);
break;
case REFUND:
processRefund(order);
break;
}
}
}

🔒 开闭原则

1
2
3
4
5
6
7
8
9
10
11
12
// 扩展新状态而不修改现有代码
public class ExpressShippingState implements OrderState {
@Override
public void handle(Order order, OrderEvent event) {
// 处理快递发货逻辑
}

@Override
public OrderStateEnum getState() {
return OrderStateEnum.EXPRESS_SHIPPING;
}
}

🤝 依赖倒置原则

1
2
3
4
5
6
7
8
9
// 通过接口依赖,而不是具体实现
public interface StateMachine {
void processEvent(StatefulEntity entity, Event event);
}

public interface OrderState {
void handle(Order order, OrderEvent event);
OrderStateEnum getState();
}

2. 性能优化

🚀 状态机池化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Service
public class StateMachinePool {

private final Map<String, StateMachine<OrderState, OrderEvent>> machinePool = new ConcurrentHashMap<>();

public StateMachine<OrderState, OrderEvent> getMachine(String machineId) {
return machinePool.computeIfAbsent(machineId, this::createMachine);
}

private StateMachine<OrderState, OrderEvent> createMachine(String machineId) {
StateMachine<OrderState, OrderEvent> machine = stateMachineFactory.create();
machine.start();
return machine;
}

// 定期清理空闲状态机
@Scheduled(fixedRate = 300000)
public void cleanupIdleMachines() {
// 清理逻辑
}
}

📊 状态缓存优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Service
public class StateCacheService {

@Autowired
private RedisTemplate<String, Object> redisTemplate;

private static final String STATE_CACHE_PREFIX = "state:cache:";

public void cacheState(String entityId, OrderState state) {
String key = STATE_CACHE_PREFIX + entityId;
redisTemplate.opsForValue().set(key, state, Duration.ofHours(1));
}

public OrderState getCachedState(String entityId) {
String key = STATE_CACHE_PREFIX + entityId;
return (OrderState) redisTemplate.opsForValue().get(key);
}

// 缓存状态变更历史
public void cacheStateHistory(String entityId, List<StateChange> history) {
String key = STATE_CACHE_PREFIX + entityId + ":history";
redisTemplate.opsForValue().set(key, history, Duration.ofDays(30));
}
}

3. 监控和调试

📈 状态机监控

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Service
@Slf4j
public class StateMachineMonitor {

private final MeterRegistry meterRegistry;
private final Map<String, Counter> transitionCounters = new ConcurrentHashMap<>();
private final Map<String, Timer> transitionTimers = new ConcurrentHashMap<>();

public void recordTransition(String machineId, OrderState from, OrderState to, OrderEvent event) {
String counterKey = String.format("state_machine.%s.transition.%s.%s.%s",
machineId, from, to, event);
transitionCounters.computeIfAbsent(counterKey, k -> Counter.builder(k).register(meterRegistry))
.increment();
}

public void recordTransitionTime(String machineId, OrderState from, OrderState to, OrderEvent event, long duration) {
String timerKey = String.format("state_machine.%s.transition_time.%s.%s.%s",
machineId, from, to, event);
transitionTimers.computeIfAbsent(timerKey, k -> Timer.builder(k).register(meterRegistry))
.record(duration, TimeUnit.MILLISECONDS);
}

// 监控状态分布
public void recordStateDistribution(String machineId, OrderState state) {
Gauge.builder("state_machine." + machineId + ".state_distribution", () -> 1)
.tag("state", state.name())
.register(meterRegistry);
}
}

🔍 状态机调试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@Service
@Slf4j
public class StateMachineDebugger {

@Autowired
private StateMachineMonitor monitor;

public void debugTransition(Order order, OrderEvent event, OrderState from, OrderState to) {
log.info("=== 状态机调试信息 ===");
log.info("订单ID: {}", order.getId());
log.info("事件: {}", event);
log.info("状态转换: {} -> {}", from, to);
log.info("订单信息: {}", order.toString());
log.info("时间戳: {}", LocalDateTime.now());

// 记录性能指标
monitor.recordTransition("order", from, to, event);

// 检查状态一致性
validateStateTransition(from, to, event);

// 输出状态转换历史
logStateHistory(order);
}

private void validateStateTransition(OrderState from, OrderState to, OrderEvent event) {
// 验证转换的合法性
boolean isValid = switch (from) {
case DRAFT -> event == OrderEvent.SUBMIT && to == OrderState.PENDING;
case PENDING -> (event == OrderEvent.PAY && to == OrderState.PAID) ||
(event == OrderEvent.CANCEL && to == OrderState.CANCELLED);
case PAID -> event == OrderEvent.SHIP && to == OrderState.SHIPPED;
// 其他状态转换规则
default -> false;
};

if (!isValid) {
log.warn("检测到异常状态转换: {} --[{}]--> {}", from, event, to);
}
}

private void logStateHistory(Order order) {
List<OrderStateHistory> history = orderStateHistoryRepository
.findByOrderIdOrderByCreatedAtDesc(order.getId());

log.info("状态变更历史:");
history.forEach(h -> log.info(" {}: {} -> {} (事件: {})",
h.getCreatedAt(), h.getFromState(),
h.getToState(), h.getEvent()));
}
}

📚 总结与建议

1. 状态机选择指南

🎯 简单业务场景

  • 推荐:枚举实现
  • 适用场景:状态较少,转换逻辑简单的业务
  • 优点:实现简单,性能好,易于理解
  • 示例:订单状态管理,用户状态管理

📈 中等复杂度业务

  • 推荐:状态模式实现
  • 适用场景:状态较多,转换逻辑相对复杂的业务
  • 优点:代码结构清晰,易于扩展和维护
  • 示例:审批工作流,任务状态管理

🏢 复杂企业级应用

  • 推荐:Spring State Machine
  • 适用场景:状态复杂,转换规则多,支持分布式部署
  • 优点:功能强大,支持持久化,监控完善
  • 示例:大型电商平台,企业级工作流系统

2. 实施建议

📋 实施步骤

  1. 需求分析:明确业务状态和转换规则
  2. 状态建模:绘制状态图,定义状态和事件
  3. 选择实现方式:根据复杂度选择合适的状态机实现
  4. 代码实现:实现状态类和转换逻辑
  5. 测试验证:编写单元测试和集成测试
  6. 监控部署:配置监控和告警
  7. 优化调优:根据实际运行情况进行优化

⚠️ 注意事项

  • 状态一致性:确保状态变更的原子性
  • 异常处理:完善的异常处理和回滚机制
  • 性能监控:实时监控状态机性能指标
  • 文档维护:及时更新状态机文档
  • 版本兼容:考虑状态机升级的兼容性

🔧 常见问题解决

  • 状态机死锁:合理设计状态转换,避免循环依赖
  • 性能问题:使用状态机池化,合理使用缓存
  • 调试困难:添加详细日志,完善监控指标
  • 扩展性问题:预留扩展接口,遵循开闭原则

3. 发展趋势

🌟 智能化状态机

  • AI驱动:使用AI预测状态转换
  • 自适应:根据历史数据自动调整转换规则
  • 自动化:自动发现和修复状态不一致问题

🔗 微服务状态机

  • 分布式协调:跨服务状态一致性保证
  • 事件驱动:基于事件的状态机协作
  • Saga模式:分布式事务的状态机实现

📊 云原生状态机

  • Kubernetes集成:使用Kubernetes原生状态管理
  • 服务网格:基于Istio的状态机编排
  • 无服务器:Serverless环境下的状态机

🔗 参考资料

📖 推荐书籍

🛠️ 工具框架

📊 在线资源


🚀 Java状态机,从简单枚举到企业级Spring State Machine的完整实现指南!

🎯 掌握状态机设计,让复杂业务流程变得清晰可控!