最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring StateMachine實(shí)現(xiàn)狀態(tài)機(jī)使用示例詳解

 更新時(shí)間:2025年07月12日 14:28:34   作者:混的Java  
本文介紹SpringStateMachine實(shí)現(xiàn)狀態(tài)機(jī)的步驟,包括依賴導(dǎo)入、枚舉定義、狀態(tài)轉(zhuǎn)移規(guī)則配置、上下文管理及服務(wù)調(diào)用示例,重點(diǎn)解析狀態(tài)同步、事件觸發(fā)與數(shù)據(jù)持久化機(jī)制,感興趣的朋友跟隨小編一起看看吧

什么是狀態(tài)機(jī)

狀態(tài)機(jī)是計(jì)算機(jī)科學(xué)中的??核心建模工具??,用于描述對(duì)象在其生命周期內(nèi)狀態(tài)變化的邏輯模型。它通過定義??有限狀態(tài)集合??、??狀態(tài)轉(zhuǎn)移規(guī)則??和??觸發(fā)事件??,精確控制系統(tǒng)的行為邏輯。

本文主要講Spring StateMachine實(shí)現(xiàn)的狀態(tài)機(jī)

使用示例

導(dǎo)入maven依賴

        <dependency>
            <groupId>org.springframework.statemachine</groupId>
            <artifactId>spring-statemachine-core</artifactId>
            <version>4.0.0</version>
        </dependency>

創(chuàng)建訂單狀態(tài)枚舉類

public enum OrderStatusEnum {
    WAITING_PAYMENT,//待支付
    WAITING_RECEIVE,//待取貨
    FINISHED,//已完成
    CANCELED;//已取消
}

創(chuàng)建訂單轉(zhuǎn)悠事件枚舉類

public enum OrderEvent {
    CREATE_ORDER,//創(chuàng)建訂單
    PAY_ORDER,//支付訂單
    RECEIVE_ORDER,//取貨
    CANCEL_ORDER,//取消訂單
    FINISH_ORDER//完成訂單
}

添加狀態(tài)機(jī)實(shí)例并添加狀態(tài)轉(zhuǎn)移規(guī)則

@Configuration
@EnableStateMachine(name="orderStateMachine")
public class OrderStateMachineConfig {
    @Bean
    public StateMachine<OrderStatusEnum, OrderEvent> orderStateMachine() throws Exception {
        StateMachineBuilder.Builder<OrderStatusEnum, OrderEvent> builder = StateMachineBuilder.builder();
        // 配置狀態(tài)
        builder.configureStates()
                .withStates()
                .initial(OrderStatusEnum.WAITING_PAYMENT) // 初始狀態(tài)
                .states(EnumSet.allOf(OrderStatusEnum.class));// 配置所有狀態(tài)
        // 配置狀態(tài)轉(zhuǎn)換 規(guī)則
        builder.configureTransitions()
                // 訂單待支付 -> 待取貨
                .withExternal()
                .source(OrderStatusEnum.WAITING_PAYMENT).target(OrderStatusEnum.WAITING_RECEIVE)
                .event(OrderEvent.PAY_ORDER)
                .and()
                // 訂單待取貨 -> 已完成
                .withExternal()
                .source(OrderStatusEnum.WAITING_RECEIVE).target(OrderStatusEnum.FINISHED)
                .event(OrderEvent.FINISH_ORDER)
                .and()
                // 訂單待支付 -> 已取消
                .withExternal()
                .source(OrderStatusEnum.WAITING_PAYMENT).target(OrderStatusEnum.CANCELED)
                .event(OrderEvent.CANCEL_ORDER);
        return builder.build();
    }
}

注入上下文bean,方法作用后面會(huì)說(shuō)

@Bean
    public DefaultStateMachinePersister persister(){
        return new DefaultStateMachinePersister<>(new StateMachinePersist<Object, Object, Order>() {
            @Override
            public void write(StateMachineContext<Object, Object> context, Order order) throws Exception {
                //此處并沒有進(jìn)行持久化操作
                System.out.println("訂單狀態(tài)持久化:" + context.getState());
            }
            @Override
            public StateMachineContext<Object, Object> read(Order order) throws Exception {
                //此處直接獲取order中的狀態(tài),其實(shí)并沒有進(jìn)行持久化讀取操作
                return new DefaultStateMachineContext(order.getStatus(), null, null, null);
            }
        });
    }

創(chuàng)建調(diào)用示例服務(wù)

@Service
@RequiredArgsConstructor
public class OrderService {
    private final StateMachine<OrderStatusEnum, OrderEvent> orderStateMachine;
    private final DefaultStateMachinePersister persister;
    // 1、事件: 支付
    // 2、狀態(tài)轉(zhuǎn)換:待支付 → 待發(fā)貨\
     public Order pay() {
         Order order = Order
                 .builder()
                 .orderId("1")
                 .status(OrderStatusEnum.WAITING_RECEIVE)
                 .build();
         System.out.println("線程名稱:" + Thread.currentThread().getName() + " 嘗試支付,訂單號(hào):" + order.getOrderId());
        Message message = MessageBuilder.withPayload(OrderEvent.PAY_ORDER).setHeader("order", order).build();
        if (!sendEvent(message, order)) {
            System.out.println("線程名稱:" + Thread.currentThread().getName() + " 支付失敗, 狀態(tài)異常,訂單號(hào):" + order.getOrderId());
        }
        System.out.println("線程名稱:" + Thread.currentThread().getName() + " 支付成功,訂單號(hào):" + order.getOrderId());
        return order;
    }
    /**
     * 發(fā)送訂單狀態(tài)轉(zhuǎn)換事件
     *
     * @param message
     * @param order
     * @return
     */
    private synchronized boolean sendEvent(Message<OrderEvent> message, Order order) {
        boolean result = false;
        try {
            orderStateMachine.start();
            //嘗試恢復(fù)狀態(tài)機(jī)狀態(tài)
            persister.restore(orderStateMachine, order);
            //添加延遲用于線程安全測(cè)試
            Thread.sleep(1000);
            result = orderStateMachine.sendEvent(message);
            //持久化狀態(tài)機(jī)狀態(tài)
            persister.persist(orderStateMachine, order);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            orderStateMachine.stop();
        }
        return result;
    }
}

代碼解析:

創(chuàng)建訂單示例模擬數(shù)據(jù)庫(kù)實(shí)際訂單信息,基于當(dāng)前訂單狀態(tài)變換的流轉(zhuǎn)與事件創(chuàng)建對(duì)應(yīng)message消息,同時(shí)添加head信息。調(diào)用sendEvent方法使用狀態(tài)機(jī)判斷。

public Order pay() {
         Order order = Order
                 .builder()
                 .orderId("1")
                 .status(OrderStatusEnum.WAITING_RECEIVE)
                 .build();
         System.out.println("線程名稱:" + Thread.currentThread().getName() + " 嘗試支付,訂單號(hào):" + order.getOrderId());
        Message message = MessageBuilder.withPayload(OrderEvent.PAY_ORDER).setHeader("order", order).build();
        if (!sendEvent(message, order)) {
            System.out.println("線程名稱:" + Thread.currentThread().getName() + " 支付失敗, 狀態(tài)異常,訂單號(hào):" + order.getOrderId());
        }
        System.out.println("線程名稱:" + Thread.currentThread().getName() + " 支付成功,訂單號(hào):" + order.getOrderId());
        return order;
    }

判斷邏輯很簡(jiǎn)單,

.start()啟動(dòng)狀態(tài)機(jī),

.restore()方法跟蹤發(fā)現(xiàn)實(shí)際調(diào)用的是上面上下文bean中的read()方法,作用是恢復(fù)狀態(tài)機(jī)的上下文,結(jié)果一番搜索后,博主終于明白這步的作用。首先我們要知道Spring StateMachine狀態(tài)機(jī)是無(wú)狀態(tài)的,每次啟動(dòng)都會(huì)是默認(rèn)的狀態(tài),而他狀態(tài)判斷邏輯不會(huì)從所有規(guī)則中尋找符合的規(guī)則,而是基于狀態(tài)機(jī)當(dāng)前的狀態(tài)與傳入的事件進(jìn)行判斷狀態(tài)流轉(zhuǎn)是否正確,因此需要將當(dāng)前狀態(tài)與狀態(tài)機(jī)中的狀態(tài)進(jìn)行同步

.sendEvent()方法是實(shí)際調(diào)用狀態(tài)機(jī)內(nèi)部的進(jìn)行狀態(tài)流轉(zhuǎn)規(guī)則的判斷,符合狀態(tài)流轉(zhuǎn)規(guī)則時(shí)對(duì)狀態(tài)進(jìn)行變換,同時(shí)符合規(guī)則轉(zhuǎn)換成功時(shí)返回true,否則返回false

通過dubug追蹤看到,狀態(tài)變換成功,同時(shí)返回true

.persist()方法內(nèi)部實(shí)際調(diào)用上下文中的write方法,可以在此進(jìn)行實(shí)際的數(shù)據(jù)持久化

接著在finally中停止?fàn)顟B(tài)機(jī)

private synchronized boolean sendEvent(Message<OrderEvent> message, Order order) {
        boolean result = false;
        try {
            orderStateMachine.start();
            //嘗試恢復(fù)狀態(tài)機(jī)狀態(tài)
            persister.restore(orderStateMachine, order);
            //添加延遲用于線程安全測(cè)試
            Thread.sleep(1000);
            result = orderStateMachine.sendEvent(message);
            //持久化狀態(tài)機(jī)狀態(tài)
            persister.persist(orderStateMachine, order);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            orderStateMachine.stop();
        }
        return result;
    }

至此,基本的狀態(tài)機(jī)就順利實(shí)現(xiàn)

到此這篇關(guān)于Spring StateMachine實(shí)現(xiàn)狀態(tài)機(jī)使用示例詳解的文章就介紹到這了,更多相關(guān)Spring StateMachine狀態(tài)機(jī)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談java接口的冪等性及解決方案

    淺談java接口的冪等性及解決方案

    本文主要介紹了java接口的冪等性及解決方案,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 淺談一下數(shù)據(jù)庫(kù)連接池Druid德魯伊

    淺談一下數(shù)據(jù)庫(kù)連接池Druid德魯伊

    數(shù)據(jù)庫(kù)連接池就是一個(gè)容器持有多個(gè)數(shù)據(jù)庫(kù)連接,當(dāng)程序需要操作數(shù)據(jù)庫(kù)的時(shí)候直接從池中取出連接,使用完之后再還回去,和線程池一個(gè)道理,需要的朋友可以參考下
    2023-05-05
  • Java實(shí)現(xiàn)順序表的操作

    Java實(shí)現(xiàn)順序表的操作

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)順序表的基本操作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 實(shí)戰(zhàn)指南:Java編寫Flink?SQL解決難題

    實(shí)戰(zhàn)指南:Java編寫Flink?SQL解決難題

    想知道如何利用Java編寫Flink?SQL解決難題嗎?本指南將為您揭示最實(shí)用的技巧和策略,讓您輕松應(yīng)對(duì)挑戰(zhàn),跟著我們一起探索,讓Java和Flink?SQL成為您問題解決的得力助手!
    2023-12-12
  • 基于java.lang.IllegalArgumentException異常報(bào)錯(cuò)問題及解決

    基于java.lang.IllegalArgumentException異常報(bào)錯(cuò)問題及解決

    這篇文章主要介紹了基于java.lang.IllegalArgumentException異常報(bào)錯(cuò)問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java8深入學(xué)習(xí)之熟透Optional

    Java8深入學(xué)習(xí)之熟透Optional

    這篇文章主要給大家介紹了關(guān)于Java8深入學(xué)習(xí)之熟透Optional的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java8具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 詳解maven的install的作用

    詳解maven的install的作用

    這篇文章主要介紹了詳解maven的install的作用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • IDEA?code?template配置和參數(shù)方式

    IDEA?code?template配置和參數(shù)方式

    這篇文章主要介紹了IDEA?code?template配置和參數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教<BR>
    2024-01-01
  • 使用BitSet位集合,一個(gè)重復(fù)校驗(yàn)工具

    使用BitSet位集合,一個(gè)重復(fù)校驗(yàn)工具

    這篇文章主要介紹了使用BitSet位集合,一個(gè)重復(fù)校驗(yàn)工具,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 使用Mybatis-plus策略自動(dòng)更新數(shù)據(jù)庫(kù)時(shí)間失敗問題解決

    使用Mybatis-plus策略自動(dòng)更新數(shù)據(jù)庫(kù)時(shí)間失敗問題解決

    這篇文章主要介紹了使用Mybatis-plus策略自動(dòng)更新數(shù)據(jù)庫(kù)時(shí)間失敗問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10

最新評(píng)論

电白县| 光山县| 商河县| 锡林浩特市| 长阳| 城固县| 文成县| 延安市| 商河县| 栖霞市| 开阳县| 横山县| 锡林郭勒盟| 惠东县| 都江堰市| 江都市| 广宁县| 炎陵县| 临颍县| 利津县| 大田县| 宣城市| 荆门市| 无为县| 新沂市| 通榆县| 香港| 许昌县| 临泉县| 永济市| 禄劝| 嘉义县| 东兴市| 太和县| 英超| 天峻县| 十堰市| 时尚| 上思县| 天镇县| 盐亭县|