spring 状态机demo

发布时间 2023-10-17 09:05:13作者: yang希军
spring 状态机demo
        <dependency>
            <groupId>org.springframework.statemachine</groupId>
            <artifactId>spring-statemachine-core</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>
// 作为数据源

public class Data {
    public static List<Order> orderList = new ArrayList<>();


    public static void create(Order order) {
        orderList.add(order);
    }


    public static Order getById(String id) {
        return orderList.stream().filter(item -> Objects.equals(id, item.getId())).findFirst().orElse(null);
    }

    public static void update(Order order) {
        orderList.stream().filter(item -> Objects.equals(order.getId(), item.getId())).findFirst().ifPresent(
                item -> item.setStatus(order.getStatus()));
    }
}
// 订单实体
public class Order {
    private String id;
    private OrderStatus status;
}
/**
 * @author yangxj
 * @date 2023/10/16 10:37
 * 状态机配置
 */
@Configuration
@EnableStateMachine(name = "orderStatemachine")
public class OrderStatemachineConfig extends StateMachineConfigurerAdapter<OrderStatus,OrderStatusChangeEvent> {


    @Bean(name = "stateMachinePersister")
    public StateMachinePersister<OrderStatus, OrderStatusChangeEvent, String> getPersister() {
        return new DefaultStateMachinePersister<>(new StateMachinePersist<OrderStatus, OrderStatusChangeEvent, String>() {
            @Override
            public void write(StateMachineContext<OrderStatus, OrderStatusChangeEvent> context, String contextObj) throws Exception {
                map.put(contextObj, context);
            }

            @Override
            public StateMachineContext<OrderStatus, OrderStatusChangeEvent> read(String contextObj) throws Exception {
                return map.get(contextObj);
            }
            Map<String, StateMachineContext<OrderStatus, OrderStatusChangeEvent>> map = new HashMap<>();
        });
    }
    /**
     * 配置状态
     */
    @Override
    public void configure(StateMachineStateConfigurer<OrderStatus, OrderStatusChangeEvent> states) throws Exception {
        states.withStates()
                .initial(OrderStatus.WAIT_PAYMENT)
                .states(EnumSet.allOf(OrderStatus.class));
    }

    /**
     * 配置转换事件
     */
    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderStatusChangeEvent> transitions) throws Exception {
        transitions
                //支付事件:待支付-》待发货
                .withExternal().source(OrderStatus.WAIT_PAYMENT).target(OrderStatus.WAIT_DELIVER).event(OrderStatusChangeEvent.PAYED_EVENT)
                .and()
                //发货事件:待发货-》待收货
                .withExternal().source(OrderStatus.WAIT_DELIVER).target(OrderStatus.WAIT_RECEIVE).event(OrderStatusChangeEvent.DELIVERED_EVENT)
                .and()
                //收货事件:待收货-》已完成
                .withExternal().source(OrderStatus.WAIT_RECEIVE).target(OrderStatus.FINISH).event(OrderStatusChangeEvent.RECEIVED_EVENT);
    }
}
// 订单状态枚举
public enum OrderStatus {
    WAIT_PAYMENT(1, "待支付"),
    WAIT_DELIVER(2, "待发货"),
    WAIT_RECEIVE(3, "待收货"),
    FINISH(4, "已完成");

    private final Integer key;
    private final String  name;

    OrderStatus(Integer key, String name) {
        this.key = key;
        this.name = name;
    }
    public Integer getKey() {
        return key;
    }
    public String getName() {
        return name;
    }
}

// 订单状态改变事件
public enum OrderStatusChangeEvent {
    // 支付,发货,确认收货
    PAYED_EVENT,
    DELIVERED_EVENT,
    RECEIVED_EVENT;
}
//  事件监听处理

@WithStateMachine(name = "orderStatemachine")
@Slf4j
public class OrderStatusChangeEventListener {

    @OnTransition(source = "WAIT_PAYMENT", target = "WAIT_DELIVER")
    public boolean payTransition(Message<OrderStatusChangeEvent> message) {
        Order order = (Order) message.getHeaders().get("order");
        log.info("支付,状态机反馈信息:{}", message.getHeaders());
        //更新订单
        order.setStatus(OrderStatus.WAIT_DELIVER);
        Data.update(order);
        return true;
    }

    @OnTransition(source = "WAIT_DELIVER", target = "WAIT_RECEIVE")
    public boolean deliverTransition(Message<OrderStatusChangeEvent> message) {
        Order order = (Order) message.getHeaders().get("order");
        log.info("发货,状态机反馈信息:{}", message.getHeaders());
        //更新订单
        order.setStatus(OrderStatus.WAIT_RECEIVE);
        Data.update(order);
        return true;
    }

    @OnTransition(source = "WAIT_RECEIVE", target = "FINISH")
    public boolean receiveTransition(Message<OrderStatusChangeEvent> message) {
        Order order = (Order) message.getHeaders().get("order");
        log.info("确认收货,状态机反馈信息:{}", message.getHeaders());
        //更新订单
        order.setStatus(OrderStatus.FINISH);
        Data.update(order);
        return true;
    }
}
@RestController
@RequestMapping("/order")
public class OrderController {  
    @Resource
    private OrderService orderService;  
    /**  
     * 根据id查询订单  
     *  
     * @return  
     */  
    @RequestMapping("/getById")  
    public Order getById(@RequestParam("id") String  id) {
        //根据id查询订单  
        Order order = orderService.getById(id);  
        return order;  
    }  
    /**  
     * 创建订单  
     *  
     * @return  
     */  
    @RequestMapping("/create")  
    public String create(@RequestBody Order order) {
        //创建订单  
        orderService.create(order);  
        return "sucess";  
    }
    /**  
     * 对订单进行支付  
     *  
     * @param id  
     * @return  
     */  
    @RequestMapping("/pay")  
    public String pay(@RequestParam("id") String id) {
        //对订单进行支付  
        orderService.pay(id);  
        return "success";  
    }  
  
    /**  
     * 对订单进行发货  
     *  
     * @param id  
     * @return  
     */  
    @RequestMapping("/deliver")  
    public String deliver(@RequestParam("id") String id) {
        //对订单进行确认收货  
        orderService.deliver(id);  
        return "success";  
    }  
    /**  
     * 对订单进行确认收货  
     *  
     * @param id  
     * @return  
     */  
    @RequestMapping("/receive")  
    public String receive(@RequestParam("id") String id) {
        //对订单进行确认收货  
        orderService.receive(id);  
        return "success";  
    }  
}  



/**
 * @author yangxj
 * @date 2023/10/16 10:55
 */
@Slf4j
@Service
public class OrderService {
    @Resource
    StateMachine<OrderStatus, OrderStatusChangeEvent> orderStateMachine;
    @Resource
    StateMachinePersister<OrderStatus, OrderStatusChangeEvent, String> stateMachinePersister;

    /**
     * 创建订单
     *
     * @param order
     * @return
     */
    public Order create(Order order) {
        order.setStatus(OrderStatus.WAIT_PAYMENT);
        Data.create(order);
        return order;
    }

    /**
     * 对订单进行支付
     *
     * @param id
     * @return
     */
    public Order pay(String id) {
        log.info("线程名称:{},尝试支付,订单号:{}", Thread.currentThread().getName(), id);
        Order order = Data.getById(id);
        if (!sendEvent(OrderStatusChangeEvent.PAYED_EVENT, order)) {
            log.error("线程名称:{},支付失败, 状态异常,订单信息:{}", Thread.currentThread().getName(), order);
            throw new RuntimeException("支付失败, 订单状态异常");
        }
        return order;
    }

    /**
     * 对订单进行发货
     *
     * @param id
     * @return
     */
    public Order deliver(String id) {
        Order order = Data.getById(id);
        log.info("线程名称:{},尝试发货,订单号:{}", Thread.currentThread().getName(), id);
        if (!sendEvent(OrderStatusChangeEvent.DELIVERED_EVENT, order)) {
            log.error("线程名称:{},发货失败, 状态异常,订单信息:{}", Thread.currentThread().getName(), order);
            throw new RuntimeException("发货失败, 订单状态异常");
        }
        return order;
    }

    /**
     * 对订单进行确认收货
     *
     * @param id
     * @return
     */
    public Order receive(String id) {
        Order order = Data.getById(id);
        log.info("线程名称:{},尝试收货,订单号:{}", Thread.currentThread().getName(), id);
        if (!sendEvent(OrderStatusChangeEvent.RECEIVED_EVENT, order)) {
            log.error("线程名称:{},收货失败, 状态异常,订单信息:{}", Thread.currentThread().getName(), order);
            throw new RuntimeException("收货失败, 订单状态异常");
        }
        return order;
    }

    /**
     * 发送订单状态转换事件
     * synchronized修饰保证这个方法是线程安全的
     *
     * @param changeEvent
     * @param order
     * @return
     */
    private synchronized boolean sendEvent(OrderStatusChangeEvent changeEvent, Order order) {
        boolean result = false;
        try {
            // 状态机重置
            stateMachinePersister.restore(orderStateMachine, order.getId());
            Message<OrderStatusChangeEvent> message = MessageBuilder.withPayload(changeEvent).setHeader("order", order).build();
            result = orderStateMachine.sendEvent(message);
            // 状态机持久化
            stateMachinePersister.persist(orderStateMachine, order.getId());
        } catch (Exception e) {
            log.error("订单操作失败, order: {}", order, e);
        } finally {
            orderStateMachine.stop();
        }
        return result;
    }

    public Order getById(String id) {
        return Data.getById(id);
    }
}