Here’s an example of an order flow:
@Data
public class Order {
private int id;
private OrderStatus status;
@Override
public String toString() {
return Order No. : + id + ", order status:+ status; }} /** * OrderStatus */ public enum OrderStatus {// OrderStatus; } /** * OrderStatusChangeEvent */ public enum OrderStatusChangeEvent { } public interface IOrderService {// create new Order Order create(); Order pay(int id); // Order deliver(int id); Order receive(int id); Map<Integer, Order> getOrders(); } @Service("orderService")
public class OrderServiceImpl implements IOrderService {
@Autowired
private StateMachine<OrderStatus, OrderStatusChangeEvent> orderStateMachine;
@Autowired
private StateMachinePersister<OrderStatus, OrderStatusChangeEvent, Order> persister;
private int id = 1;
private Map<Integer, Order> orders = new HashMap<>();
public Order create() {
Order order = new Order();
order.setStatus(OrderStatus.WAIT_PAYMENT);
order.setId(id++);
orders.put(order.getId(), order);
return order;
}
public Order pay(int id) {
Order order = orders.get(id);
System.out.println("Thread name:" + Thread.currentThread().getName() + "Attempt payment, Order No. :" + id);
Message message = MessageBuilder.withPayload(OrderStatusChangeEvent.PAYED).setHeader("order", order).build();
if(! sendEvent(message, order)) { System.out.println("Thread name:" + Thread.currentThread().getName() + "Payment failed, status abnormal, order No. :" + id);
}
return orders.get(id);
}
public Order deliver(int id) {
Order order = orders.get(id);
System.out.println("Thread name:" + Thread.currentThread().getName() + "Attempted shipment, Order No. :" + id);
if(! sendEvent(MessageBuilder.withPayload(OrderStatusChangeEvent.DELIVERY).setHeader("order", order).build(), orders.get(id))) {
System.out.println("Thread name:" + Thread.currentThread().getName() + "Delivery failure, abnormal status, order No. :" + id);
}
return orders.get(id);
}
public Order receive(int id) {
Order order = orders.get(id);
System.out.println("Thread name:" + Thread.currentThread().getName() + "Try to receive goods, order no. :" + id);
if(! sendEvent(MessageBuilder.withPayload(OrderStatusChangeEvent.RECEIVED).setHeader("order", order).build(), orders.get(id))) {
System.out.println("Thread name:" + Thread.currentThread().getName() + "Failed to receive, abnormal status, order No. :" + id);
}
return orders.get(id);
}
public Map<Integer, Order> getOrders() {
returnorders; } /** * send the order status transition event ** @param message * @param order * @return
*/
private synchronized boolean sendEvent(Message<OrderStatusChangeEvent> message, Order order) {
boolean result = false; try { orderStateMachine.start(); // Try to restore the state machine state persister.restore(orderStateMachine, order); // Add delay for Thread safety test thread.sleep (1000); result = orderStateMachine.sendEvent(message); // Persist state machine state persister.persist(orderStateMachine, order); } catch (Exception e) { e.printStackTrace(); } finally { orderStateMachine.stop(); }returnresult; } } package com.gupaoedu.vip.pattern.state.order; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.statemachine.StateMachineContext; import org.springframework.statemachine.StateMachinePersist; import org.springframework.statemachine.config.EnableStateMachine; import org.springframework.statemachine.config.StateMachineConfigurerAdapter; import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; import org.springframework.statemachine.persist.DefaultStateMachinePersister; import org.springframework.statemachine.support.DefaultStateMachineContext; import java.util.EnumSet; /** * Order state machine Configuration */ @configuration@enableStatemachine (name ="orderStateMachine") public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderStatus, OrderStatusChangeEvent> {/** * configuration status * @param States * @throws Exception */ public void configure(StateMachineStateConfigurer<OrderStatus, OrderStatusChangeEvent> states) throws Exception { states .withStates() .initial(OrderStatus.WAIT_PAYMENT) .states(EnumSet.allOf(OrderStatus.class)); } /** * Configure the state transition event relationship * @param Transitions * @throws Exception */ public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderStatusChangeEvent> transitions) throws Exception { transitions .withExternal().source(OrderStatus.WAIT_PAYMENT).target(OrderStatus.WAIT_DELIVER).event(OrderStatusChangeEvent.PAYED) .and() .withExternal().source(OrderStatus.WAIT_DELIVER).target(OrderStatus.WAIT_RECEIVE).event(OrderStatusChangeEvent.DELIVERY) .and() .withExternal().source(OrderStatus.WAIT_RECEIVE).target(OrderStatus.FINISH).event(OrderStatusChangeEvent.RECEIVED); } /** * Persistent configuration * in actual use, you can cooperate with redis, etc., for persistent operation * @return
*/
@Bean
public DefaultStateMachinePersister persister() {returnnew DefaultStateMachinePersister<>(new StateMachinePersist<Object, Object, Order>() { @Override public void write(StateMachineContext<Object, Object> context, Override public StateMachineContext<Object, Object>read(Order Order) throws Exception {// The state in Order is directly obtained without a persistent read operationreturnnew DefaultStateMachineContext(order.getStatus(), null, null, null); }}); } } import org.springframework.messaging.Message; import org.springframework.statemachine.annotation.OnTransition; import org.springframework.statemachine.annotation.WithStateMachine; import org.springframework.stereotype.Component; @Component("orderStateListener")
@WithStateMachine(name = "orderStateMachine")
public class OrderStateListenerImpl{
@OnTransition(source = "WAIT_PAYMENT", target = "WAIT_DELIVER")
public boolean payTransition(Message<OrderStatusChangeEvent> message) {
Order order = (Order) message.getHeaders().get("order");
order.setStatus(OrderStatus.WAIT_DELIVER);
System.out.println("Payment, state machine feedback:" + message.getHeaders().toString());
return true;
}
@OnTransition(source = "WAIT_DELIVER", target = "WAIT_RECEIVE")
public boolean deliverTransition(Message<OrderStatusChangeEvent> message) {
Order order = (Order) message.getHeaders().get("order");
order.setStatus(OrderStatus.WAIT_RECEIVE);
System.out.println("Delivery, state machine feedback:" + message.getHeaders().toString());
return true;
}
@OnTransition(source = "WAIT_RECEIVE", target = "FINISH")
public boolean receiveTransition(Message<OrderStatusChangeEvent> message){
Order order = (Order) message.getHeaders().get("order");
order.setStatus(OrderStatus.FINISH);
System.out.println("Received goods, state machine feedback information:" + message.getHeaders().toString());
return true;
}
}
@SpringBootApplication
public class Test {
public static void main(String[] args) {
Thread.currentThread().setName("Main thread");
ConfigurableApplicationContext context = SpringApplication.run(Test.class,args);
IOrderService orderService = (IOrderService)context.getBean("orderService");
orderService.create();
orderService.create();
orderService.pay(1);
new Thread("Client thread"){
@Override
public void run() {
orderService.deliver(1);
orderService.receive(1);
}
}.start();
orderService.pay(2);
orderService.deliver(2);
orderService.receive(2);
System.out.println("Status of all orders:"+ orderService.getOrders()); }}Copy the code