Understanding the State Pattern and Implementing Order Workflow with Spring State Machine
This article explains the State design pattern, demonstrates its Java implementation with example code, introduces Spring State Machine concepts, and provides a complete step‑by‑step guide to building and testing an order status workflow using Spring State Machine, including configuration, listeners, services, and a controller.
The article begins by introducing the State design pattern, describing its purpose of encapsulating varying behavior based on an object's internal state and presenting a class diagram that includes Context, Abstract State, and Concrete State roles.
It then provides a simple Java example of the pattern using a traffic‑light scenario, with the following code snippets:
public abstract class MyState {
abstract void handler();
}
public class RedLightState extends MyState {
@Override
void handler() {
System.out.println("红灯停");
}
}
public class GreenLightState extends MyState {
@Override
void handler() {
System.out.println("绿灯行");
}
}
public class MyContext {
private MyState state;
public void setState(MyState state) { this.state = state; }
public void handler() { state.handler(); }
}
public class TestStateModel {
public static void main(String[] args) {
MyContext ctx = new MyContext();
ctx.setState(new RedLightState());
ctx.handler(); // 红灯停
ctx.setState(new GreenLightState());
ctx.handler(); // 绿灯行
}
}After confirming the pattern, the article shifts focus to Spring State Machine, defining its elements (current state, trigger event, response function, target state) and comparing it with the COLA state machine.
It then walks through building an order‑status workflow using Spring State Machine, starting with Maven dependency configuration:
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-core</artifactId>
<version>${springboot.version}</version>
</dependency>Domain model definitions:
public class Order {
private Long orderId;
private OrderStatusEnum orderStatus;
}
public enum OrderStatusEnum { WAIT_PAYMENT, WAIT_DELIVER, WAIT_RECEIVE, FINISH; }
public enum OrderStatusChangeEventEnum { PAYED, DELIVERY, RECEIVED; }State machine configuration class:
@Configuration
@EnableStateMachine
public class OrderStatusMachineConfig extends StateMachineConfigurerAdapter
{
@Override
public void configure(StateMachineStateConfigurer
states) throws Exception {
states.withStates()
.initial(OrderStatusEnum.WAIT_PAYMENT)
.end(OrderStatusEnum.FINISH)
.states(EnumSet.allOf(OrderStatusEnum.class));
}
@Override
public void configure(StateMachineTransitionConfigurer
transitions) throws Exception {
transitions.withExternal().source(OrderStatusEnum.WAIT_PAYMENT).target(OrderStatusEnum.WAIT_DELIVER).event(OrderStatusChangeEventEnum.PAYED)
.and()
.withExternal().source(OrderStatusEnum.WAIT_DELIVER).target(OrderStatusEnum.WAIT_RECEIVE).event(OrderStatusChangeEventEnum.DELIVERY)
.and()
.withExternal().source(OrderStatusEnum.WAIT_RECEIVE).target(OrderStatusEnum.FINISH).event(OrderStatusChangeEventEnum.RECEIVED);
}
}Listener that updates the Order entity on state transitions:
@Component
@WithStateMachine
@Transactional
public class OrderStatusListener {
@OnTransition(source = "WAIT_PAYMENT", target = "WAIT_DELIVER")
public boolean payTransition(Message message) {
Order order = (Order) message.getHeaders().get("order");
order.setOrderStatus(OrderStatusEnum.WAIT_DELIVER);
System.out.println("支付,状态机反馈信息:" + message.getHeaders().toString());
return true;
}
@OnTransition(source = "WAIT_DELIVER", target = "WAIT_RECEIVE")
public boolean deliverTransition(Message message) {
Order order = (Order) message.getHeaders().get("order");
order.setOrderStatus(OrderStatusEnum.WAIT_RECEIVE);
System.out.println("发货,状态机反馈信息:" + message.getHeaders().toString());
return true;
}
@OnTransition(source = "WAIT_RECEIVE", target = "FINISH")
public boolean receiveTransition(Message message) {
Order order = (Order) message.getHeaders().get("order");
order.setOrderStatus(OrderStatusEnum.FINISH);
System.out.println("收货,状态机反馈信息:" + message.getHeaders().toString());
return true;
}
}Service implementation that creates orders and triggers state‑change events:
@Service
public class OrderServiceImpl implements OrderService {
@Resource
private StateMachine
orderStateMachine;
private long id = 1L;
private Map
orders = Maps.newConcurrentMap();
@Override
public Order create() {
Order order = new Order();
order.setOrderStatus(OrderStatusEnum.WAIT_PAYMENT);
order.setOrderId(id++);
orders.put(order.getOrderId(), order);
System.out.println("订单创建成功:" + order);
return order;
}
// pay, deliver, receive methods omitted for brevity – they build a Message with the appropriate event and call sendEvent(message)
private synchronized boolean sendEvent(Message
message) {
boolean result = false;
try {
orderStateMachine.start();
result = orderStateMachine.sendEvent(message);
} catch (Exception e) { e.printStackTrace(); }
finally {
if (Objects.nonNull(message)) {
Order order = (Order) message.getHeaders().get("order");
if (Objects.nonNull(order) && Objects.equals(order.getOrderStatus(), OrderStatusEnum.FINISH)) {
orderStateMachine.stop();
}
}
}
return result;
}
}Controller that exercises the whole flow in a single endpoint:
@RestController
public class OrderController {
@Resource
private OrderService orderService;
@RequestMapping("/testOrderStatusChange")
public String testOrderStatusChange() {
orderService.create();
orderService.create();
orderService.pay(1L);
orderService.deliver(1L);
orderService.receive(1L);
orderService.pay(2L);
orderService.deliver(2L);
orderService.receive(2L);
System.out.println("全部订单状态:" + orderService.getOrders());
return "success";
}
}The execution results (shown as images in the original article) confirm that the Spring State Machine correctly drives the order through the states WAIT_PAYMENT → WAIT_DELIVER → WAIT_RECEIVE → FINISH.
Finally, the article discusses alternative ways to implement state machines, such as using message queues, scheduled jobs, or rule engines, and concludes that the presented approach combines the clarity of the State pattern with the powerful features of Spring State Machine for managing complex business workflows.
Java Architect Essentials
Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.