偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

業(yè)務流程場景的處理利器—Spring狀態(tài)機

開發(fā) 前端
Spring狀態(tài)機的核心在于狀態(tài)變遷和事件驅動,它強調的是系統當前所處的狀態(tài),并且關注于系統如何根據接收到的外部事件或內部條件進行狀態(tài)轉變。

在日常開發(fā)系統中經常會涉及到一些狀態(tài)管理的場景,典型的如訂單場景,訂單從創(chuàng)建到最終完成或取消,通常會經歷多個狀態(tài)的轉換,那么如何高效地管理這些狀態(tài)流轉,并在系統中靈活地擴展狀態(tài)和行為呢?Spring狀態(tài)機可以很好的幫助解決我們的實際問題。

1、認識Spring狀態(tài)機

Spring狀態(tài)機(稱為Spring State Machine)是一種可以管理狀態(tài)、事件之間的關系,以及他們之間的轉換。這是一個專門為應用程序中的狀態(tài)管理和狀態(tài)轉換提供支持的框架。它簡化了事物對象在不同狀態(tài)下,不同事件轉化的代碼管理,讓其代碼變得更加清晰明了。

在我們的日常生活中電梯是我們非常熟悉的老伙計,電梯有停止、運行、開門、關門等狀態(tài)。如果我們按了某一層按了電梯按鈕(事件),電梯會進入運行狀態(tài),并且運行到目標樓層,然后停止并開門等一系列的動作。類比電梯的運行,Spring的狀態(tài)機也是在有限個狀態(tài)以及這些狀態(tài)之間的轉移和動作等行為,Spring狀態(tài)機的核心概念:

(1)狀態(tài) (State):定義系統可以存在的各個狀態(tài),如電梯的不同階段(停止、運行、開門、關門)。

(2)事件(Event):觸發(fā)狀態(tài)變遷的動作或條件,如用戶點擊“5f”按鈕觸發(fā)電梯的運行事件。

(3)轉換(Transition):定義了在特定狀態(tài)下接收到特定事件時,如何從一個狀態(tài)遷移到另一個狀態(tài)。

(4)動作(Action):可以在狀態(tài)變遷前后執(zhí)行的操作,如狀態(tài)切換時更新數據庫記錄、發(fā)送通知郵件等。

Spring狀態(tài)機的核心在于狀態(tài)變遷和事件驅動,它強調的是系統當前所處的狀態(tài),并且關注于系統如何根據接收到的外部事件或內部條件進行狀態(tài)轉變。

2、實戰(zhàn)Spring狀態(tài)機

我們以典型的電商場景下的訂單狀態(tài)為例,介紹Spring狀態(tài)機如何實現訂單狀態(tài)的高效管理,訂單的狀態(tài)流轉圖如下所示:

圖片圖片

項目的基礎結構圖如下所示:

圖片圖片

(1)添加的spring狀態(tài)機依賴

<dependency>
    <groupId>org.springframework.statemachine</groupId>
    <artifactId>spring-statemachine-starter</artifactId>
    <version>2.5.1</version>
</dependenc

(2)定義訂單的狀態(tài)

@Getter
@AllArgsConstructor
public enum OrderStatusEnum {
    WAIT_PAY(0, "待支付"),
    WAIT_DELIVER(1, "待發(fā)貨"),
    WAIT_RECEIVE(2, "待收貨"),
    RECEIVED(3, "已收貨");


    private Integer code;
    private String msg;
}

(3)定義訂單的事件

@Getter
@AllArgsConstructor
public enum OrderStatusEventEnum {
    ORDER(1, "用戶下單"),
    PAY(2, "用戶支付"),
    DELIVER(3, "倉庫發(fā)貨"),
    RECEIVE(4, "用戶收貨")
    ;
    private final Integer code;
    private final String msg;
}

(4)定義訂單狀態(tài)的流轉和初始化

@Configurable
@EnableStateMachine(name ="orderStateMachine")    //name的作用是給狀態(tài)機制命名,用于區(qū)分不同的狀態(tài)機
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderStatusEnum, OrderStatusEventEnum> {


    /**
     * 初始化
     *
     */
    @Override
    public void configure(StateMachineStateConfigurer<OrderStatusEnum, OrderStatusEventEnum> states) throws Exception {
       states.withStates()
                .initial(OrderStatusEnum.WAIT_PAY)   //初始化訂單的狀態(tài)
                .states(EnumSet.allOf(OrderStatusEnum.class));    //列舉訂單所有的預設狀態(tài)
    }


    /**
     * 配置訂單狀態(tài)的流轉和觸發(fā)事件
     *
     */
    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStatusEnum, OrderStatusEventEnum> transitions) throws Exception {
        transitions
                // 通過支付事件  將訂單從待支付 -> 待發(fā)貨狀態(tài)(支付成功)
                .withExternal().source(OrderStatusEnum.WAIT_PAY).target(OrderStatusEnum.WAIT_DELIVER).event(OrderStatusEventEnum.PAY)
                .and()
                // 通過發(fā)貨事件  已支將訂單從待發(fā)貨 -> 待收貨狀態(tài)
                .withExternal().source(OrderStatusEnum.WAIT_DELIVER).target(OrderStatusEnum.WAIT_RECEIVE).event(OrderStatusEventEnum.DELIVER)
                .and()
                // 通過用戶接收事件 將訂單從待收貨 -> 已收貨狀態(tài)
                .withExternal().source(OrderStatusEnum.WAIT_RECEIVE).target(OrderStatusEnum.RECEIVED).event(OrderStatusEventEnum.RECEIVE);
    }
}

通過上面的配置就可以實現訂單狀態(tài)直接的轉換,主要用于說明訂單的狀態(tài)和事件的綁定關系,并且指明了訂單狀態(tài)如何流轉的(原始狀態(tài)是什么,目標的狀態(tài)是什么 ,通過什么事件觸發(fā))。

(5)定義監(jiān)聽

訂單的節(jié)點已經定義,那么每個節(jié)點是如何工作的呢?此時需要配置監(jiān)聽,用于實現當狀態(tài)發(fā)生變化的時候需要完成什么動作。

@Slf4j
@Component
@WithStateMachine(name = "orderStateMachine")
public class OrderMachineListener {


    @OnTransition(source = "WAIT_PAY", target = "WAIT_DELIVER")
    public void pay(Message<OrderStatusEventEnum> message) {
        // 獲取消息頭中的order對象
        OrderEntity entity = message.getHeaders().get("order", OrderEntity.class);
        entity.setStatus(OrderStatusEnum.WAIT_DELIVER.getCode());
        System.out.println("orderMachine   WAIT_PAY----> WAIT_DELIVER");
    }


    @OnTransition(source = "WAIT_DELIVER", target = "WAIT_RECEIVE")
    public void delivery(Message<OrderStatusEventEnum> message) {
        // 獲取消息頭中的order對象
        OrderEntity entity = message.getHeaders().get("order", OrderEntity.class);
        entity.setStatus(OrderStatusEnum.WAIT_DELIVER.getCode());
        System.out.println("orderMachine   WAIT_DELIVER----> WAIT_RECEIVE");
    }


    @OnTransition(source = "WAIT_RECEIVE", target = "RECEIVED")
    public void received(Message<OrderStatusEventEnum> message) {
        // 獲取消息頭中的order對象
        OrderEntity entity = message.getHeaders().get("order", OrderEntity.class);
        entity.setStatus(OrderStatusEnum.WAIT_DELIVER.getCode());
        System.out.println("orderMachine   WAIT_RECEIVE----> RECEIVED");
    }
}

(6)觸發(fā)狀態(tài)機的工作

訂單狀態(tài)機整個生命周期的狀態(tài)定義完成、訂單的狀態(tài)發(fā)生了轉換后需要執(zhí)行的行為也定義完成,那么如何觸發(fā)整個鏈路工作呢?此時就需要加入觸發(fā)的入口:

@Component
@Slf4j
public class OrderProcessorService {


    @Resource
    private StateMachine<OrderStatusEnum, OrderStatusEventEnum> orderStatusMachine;


    public Boolean process(OrderEntity order, OrderStatusEventEnum event) {
        orderStatusMachine.start();
        //訂單的對象封裝到message中
        Message<OrderStatusEventEnum> message = MessageBuilder.withPayload(event).
                setHeader("order",order).
                build();
        //使用狀態(tài)機發(fā)送這個消息
        return this.touchEvent(message);
    }




    private boolean touchEvent(Message<OrderStatusEventEnum> message) {
        OrderEntity order = (OrderEntity)message.getHeaders().get("order");
        System.out.println("訂單的信息 orderId=" + (Objects.nonNull(order) ? order.getId() : "-"));
        return orderStatusMachine.sendEvent(message);
    }
}

sendEvent(message)是十分關鍵的,因為在這里只要輸入什么樣的事件,那么它就按照預先設定的規(guī)則觸發(fā)狀態(tài)的流轉,并執(zhí)行監(jiān)聽中方法。

(7)測試Conrtoller

@RestController
@RequestMapping("/order")
public class OrderController {
    @Resource
    private OrderProcessorService orderProcessorService;


    @GetMapping("/pay")
    public String pay(Integer orderId) {


        OrderEntity order = new OrderEntity();
        order.setId(orderId);
        order.setStatus(OrderStatusEnum.WAIT_PAY.getCode());
        orderProcessorService.process(order, OrderStatusEventEnum.PAY);
        return "pay success";
    }


    @GetMapping("/deliver")
    public String deliver(Integer orderId) {


        OrderEntity order = new OrderEntity();
        order.setId(orderId);
        order.setStatus(OrderStatusEnum.WAIT_DELIVER.getCode());
        orderProcessorService.process(order, OrderStatusEventEnum.DELIVER);
        return "deliver success";
    }


    @GetMapping("/receive")
    public String receive(Integer orderId) {


        OrderEntity order = new OrderEntity();
        order.setId(orderId);
        order.setStatus(OrderStatusEnum.WAIT_RECEIVE.getCode());
        orderProcessorService.process(order, OrderStatusEventEnum.RECEIVE);
        return "receive success";
    }
}

(8)執(zhí)行的結果

(a)支付的狀態(tài)流轉

圖片圖片

控制臺的輸出結果:

圖片圖片

(b)發(fā)貨的狀態(tài)流轉

圖片圖片

控制臺的輸出結果:

圖片圖片

(c)收貨狀態(tài)的流轉

圖片圖片

控制臺的輸出結果:

圖片圖片

    至此,我們實現使用Spring狀態(tài)機實現了訂單的狀態(tài)流轉和觸發(fā)對應的事件。

總結

(1)如果業(yè)務流程復雜,狀態(tài)多,狀態(tài)切換頻繁,Spring狀態(tài)機就非常的適用,它可以提升代碼的維護性和擴展性。

(2)Spring狀態(tài)機可以直接集成到現有的服務中,適合高并發(fā)低延遲的場景,涉及到單個流程的流轉業(yè)務,可以考慮使用狀態(tài)機。

責任編輯:武曉燕 來源: 龍蝦編程
相關推薦

2020-06-19 12:23:05

CIO數據分析技術

2010-06-29 15:45:57

UML業(yè)務流程

2013-11-06 14:15:11

流程

2020-01-19 20:07:32

物聯網大數據IOT

2025-10-29 07:38:45

2022-05-28 16:08:04

前端

2023-03-06 07:35:30

狀態(tài)機工具訂單狀態(tài)

2010-02-04 13:57:19

ibmdwWebsphere

2013-11-06 14:16:23

流程

2025-01-20 00:00:03

高并發(fā)秒殺業(yè)務

2025-08-28 01:12:00

狀態(tài)機系統編排

2021-05-06 17:22:22

區(qū)塊鏈加密貨幣技術

2011-05-18 11:34:54

云端業(yè)務流程管理

2010-06-18 12:38:38

UML狀態(tài)機視圖

2025-08-28 04:25:00

BPMN業(yè)務流程優(yōu)化

2020-03-27 10:50:29

DSL 狀態(tài)機工具

2013-09-03 09:57:43

JavaScript有限狀態(tài)機

2010-06-18 13:25:44

UML狀態(tài)機視圖

2024-10-11 11:19:05

LiteFlow框架流程

2021-07-08 09:15:20

單片機編程狀態(tài)機編程語言
點贊
收藏

51CTO技術棧公眾號