Spring Boot集成Spring Statemachine

Spring Statemachine 是 Spring 框架下的一個模塊,用于簡化狀態機的創建和管理,它允許開發者使用 Spring 的特性(如依賴注入、AOP 等)來構建復雜的狀態機應用。以下是關于 Spring Statemachine 的詳細介紹:

主要特性

  1. 豐富的狀態機模型支持:支持多種狀態機模型,如簡單狀態機、層次狀態機和并行狀態機。層次狀態機允許狀態嵌套,并行狀態機可以同時處理多個獨立的狀態流。
  2. 靈活的配置方式:可以使用 Java 配置、XML 配置或注解來定義狀態機的狀態、轉移、事件等。
  3. 與 Spring 生態集成:無縫集成 Spring 框架的其他模塊,如 Spring Boot、Spring MVC 等,方便構建企業級應用。
  4. 事件驅動機制:通過事件觸發狀態轉移,易于與外部系統進行交互。
  5. 狀態監聽器:允許開發者在狀態轉移前后執行自定義邏輯,如日志記錄、業務處理等。

快速入門

1. 添加依賴

如果你使用 Maven,在?pom.xml?中添加以下依賴:

xml

<dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-core</artifactId><version>3.2.1</version>
</dependency>
2. 定義狀態和事件

java

// 定義狀態枚舉
public enum States {STATE1, STATE2, STATE3
}// 定義事件枚舉
public enum Events {EVENT1, EVENT2
}
3. 配置狀態機

使用 Java 配置方式:

java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;import java.util.EnumSet;@Configuration
@EnableStateMachine
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<States, Events> {@Overridepublic void configure(StateMachineConfigurationConfigurer<States, Events> config) throws Exception {config.withConfiguration().autoStartup(true);}@Overridepublic void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {states.withStates().initial(States.STATE1).states(EnumSet.allOf(States.class));}@Overridepublic void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {transitions.withExternal().source(States.STATE1).target(States.STATE2).event(Events.EVENT1).and().withExternal().source(States.STATE2).target(States.STATE3).event(Events.EVENT2);}
}
4. 使用狀態機

java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.statemachine.StateMachine;@SpringBootApplication
public class StateMachineApp implements CommandLineRunner {@Autowiredprivate StateMachine<States, Events> stateMachine;public static void main(String[] args) {SpringApplication.run(StateMachineApp.class, args);}@Overridepublic void run(String... args) throws Exception {stateMachine.start();System.out.println("當前狀態: " + stateMachine.getState().getId());stateMachine.sendEvent(Events.EVENT1);System.out.println("觸發 EVENT1 后狀態: " + stateMachine.getState().getId());stateMachine.sendEvent(Events.EVENT2);System.out.println("觸發 EVENT2 后狀態: " + stateMachine.getState().getId());}
}

代碼解釋

  1. 定義狀態和事件:使用枚舉類型定義狀態機的狀態和事件,方便管理和使用。
  2. @Configuration:表明這是一個配置類。
  3. @EnableStateMachine:啟用狀態機功能。
  4. 配置狀態機
    • configure(StateMachineConfigurationConfigurer):配置狀態機的基本屬性,如自動啟動。
    • configure(StateMachineStateConfigurer):定義狀態機的狀態,指定初始狀態STATE_A和所有可能的狀態。
    • configure(StateMachineTransitionConfigurer):定義狀態之間的轉移規則,包括源狀態、目標狀態和觸發事件。EVENT_1?事件觸發從?STATE_A?到?STATE_B?的轉移,EVENT_2?事件觸發從?STATE_B?到?STATE_C?的轉移。
  5. 使用狀態機:在?CommandLineRunner?中注入狀態機實例,啟動狀態機并發送事件,觀察狀態的變化。

應用場景

  1. 工作流管理:如訂單處理流程、審批流程等,通過狀態機可以清晰地管理每個步驟的狀態轉換。
  2. 游戲開發:管理游戲角色的狀態,如站立、行走、攻擊等,根據用戶輸入和游戲邏輯進行狀態轉移。
  3. 設備控制:控制物聯網設備的狀態,如智能家電的開關、模式切換等。

Spring Statemachine 提供了強大而靈活的功能,幫助開發者更高效地實現狀態機應用。

-----------------------------------------------DEMO------------------------------------------------------------------

以下為你提供一個較為完整的 Spring Boot 集成 Spring Statemachine 的示例代碼,這個示例模擬了一個簡單的訂單狀態機,包含待支付、已支付、已發貨、已完成幾種狀態。

1. 創建 Spring Boot 項目并添加依賴

可以使用 Spring Initializr 或者 IDE 自帶的 Spring Boot 項目創建功能,添加以下依賴:

xml

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-core</artifactId><version>3.2.1</version></dependency>
</dependencies>

2. 定義狀態和事件枚舉

java

// 定義訂單狀態枚舉
public enum OrderState {PENDING_PAYMENT, PAID, SHIPPED, COMPLETED
}// 定義訂單事件枚舉
public enum OrderEvent {PAY, SHIP, DELIVER
}

3. 配置狀態機

java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;import java.util.EnumSet;@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends EnumStateMachineConfigurerAdapter<OrderState, OrderEvent> {@Overridepublic void configure(StateMachineConfigurationConfigurer<OrderState, OrderEvent> config) throws Exception {config.withConfiguration().autoStartup(true);}@Overridepublic void configure(StateMachineStateConfigurer<OrderState, OrderEvent> states) throws Exception {states.withStates().initial(OrderState.PENDING_PAYMENT).states(EnumSet.allOf(OrderState.class));}@Overridepublic void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception {transitions.withExternal().source(OrderState.PENDING_PAYMENT).target(OrderState.PAID).event(OrderEvent.PAY).and().withExternal().source(OrderState.PAID).target(OrderState.SHIPPED).event(OrderEvent.SHIP).and().withExternal().source(OrderState.SHIPPED).target(OrderState.COMPLETED).event(OrderEvent.DELIVER);}
}

4. 創建狀態機服務類

java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.statemachine.StateMachine;
import org.springframework.stereotype.Service;@Service
public class OrderStateMachineService {@Autowiredprivate StateMachine<OrderState, OrderEvent> stateMachine;public boolean sendEvent(OrderEvent event) {return stateMachine.sendEvent(event);}public OrderState getCurrentState() {return stateMachine.getState().getId();}
}

5. 創建控制器類

java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/order")
public class OrderController {@Autowiredprivate OrderStateMachineService orderStateMachineService;@GetMapping("/currentState")public OrderState getCurrentState() {return orderStateMachineService.getCurrentState();}@PostMapping("/sendEvent/{event}")public String sendEvent(@PathVariable OrderEvent event) {boolean result = orderStateMachineService.sendEvent(event);if (result) {return "事件發送成功,當前狀態: " + orderStateMachineService.getCurrentState();} else {return "事件發送失敗,當前狀態: " + orderStateMachineService.getCurrentState();}}
}

6. 啟動 Spring Boot 應用

java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringStatemachineDemoApplication {public static void main(String[] args) {SpringApplication.run(SpringStatemachineDemoApplication.class, args);}
}

代碼解釋

  • 狀態和事件枚舉OrderState?定義了訂單可能的狀態,OrderEvent?定義了觸發狀態轉移的事件。
  • 狀態機配置OrderStateMachineConfig?類使用?@EnableStateMachine?注解啟用狀態機,通過重寫三個配置方法分別配置狀態機的基本屬性、狀態和轉移規則。
  • 狀態機服務類OrderStateMachineService?封裝了狀態機的操作,包括發送事件和獲取當前狀態。
  • 控制器類OrderController?提供了兩個接口,一個用于獲取當前訂單狀態,另一個用于發送事件觸發狀態轉移。
  • 啟動類SpringStatemachineDemoApplication?是 Spring Boot 應用的啟動類。

測試

啟動應用后,可以使用以下方式進行測試:

  • 獲取當前狀態:訪問?http://localhost:8080/order/currentState
  • 發送事件:訪問?http://localhost:8080/order/sendEvent/PAY?觸發支付事件,根據狀態機配置,訂單狀態將從?PENDING_PAYMENT?轉移到?PAID

------------------------------------------------------------------------------------------------

transitions.withExternal().source(OrderState.PENDING_PAYMENT).target(OrderState.PAID).event(OrderEvent.PAY).and().withExternal().source(OrderState.PAID).target(OrderState.SHIPPED).event(OrderEvent.SHIP).and().withExternal().source(OrderState.SHIPPED).target(OrderState.COMPLETED).event(OrderEvent.DELIVER);

這段代碼的主要作用是定義狀態機中不同狀態之間的轉移規則。在一個訂單處理的狀態機場景里,它明確了訂單在不同狀態(如待支付、已支付、已發貨、已完成)之間如何根據特定事件(如支付、發貨、交付)進行轉換。

代碼結構分析

整體上,這段代碼通過多次調用?withExternal()?方法來定義多個外部狀態轉移規則,每個狀態轉移規則由?source(源狀態)、target(目標狀態)和?event(觸發事件)三個關鍵部分組成,不同的狀態轉移規則之間通過?.and()?方法進行連接。

各部分詳細解釋

withExternal()

withExternal()?方法用于定義外部狀態轉移,即狀態機從一個狀態轉移到另一個不同的狀態。與之相對的還有內部轉移(withInternal()),內部轉移不會改變狀態機的狀態,只是在當前狀態下執行一些操作。

.source(OrderState.PENDING_PAYMENT).target(OrderState.PAID).event(OrderEvent.PAY)
  • source(OrderState.PENDING_PAYMENT):指定狀態轉移的起始狀態,這里是?OrderState.PENDING_PAYMENT,表示訂單處于待支付狀態。
  • target(OrderState.PAID):指定狀態轉移的目標狀態,即?OrderState.PAID,意味著訂單在滿足條件后將轉移到已支付狀態。
  • event(OrderEvent.PAY):指定觸發狀態轉移的事件,當?OrderEvent.PAY?事件發生時,狀態機將從待支付狀態轉移到已支付狀態。
.and()

and()?方法用于連接多個狀態轉移規則,它表示一個規則定義的結束和下一個規則定義的開始,使得可以在同一個配置方法中定義多個不同的狀態轉移規則。

后續規則

java

.withExternal().source(OrderState.PAID).target(OrderState.SHIPPED).event(OrderEvent.SHIP)
.and()
.withExternal().source(OrderState.SHIPPED).target(OrderState.COMPLETED).event(OrderEvent.DELIVER);

這部分代碼定義了另外兩個狀態轉移規則:

  • 當?OrderEvent.SHIP?事件發生時,訂單從已支付狀態(OrderState.PAID)轉移到已發貨狀態(OrderState.SHIPPED)。
  • 當?OrderEvent.DELIVER?事件發生時,訂單從已發貨狀態(OrderState.SHIPPED)轉移到已完成狀態(OrderState.COMPLETED)。

示例代碼擴展

如果需要在狀態轉移時執行一些額外的操作,比如記錄日志或者更新數據庫,可以使用?action()?方法。以下是一個擴展后的示例:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;import java.util.EnumSet;@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends EnumStateMachineConfigurerAdapter<OrderState, OrderEvent> {@Overridepublic void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception {Action<OrderState, OrderEvent> payAction = context -> {System.out.println("訂單已支付,更新訂單狀態為已支付");// 這里可以添加更新數據庫等操作};Action<OrderState, OrderEvent> shipAction = context -> {System.out.println("訂單已發貨,更新訂單狀態為已發貨");// 這里可以添加更新數據庫等操作};Action<OrderState, OrderEvent> deliverAction = context -> {System.out.println("訂單已完成,更新訂單狀態為已完成");// 這里可以添加更新數據庫等操作};transitions.withExternal().source(OrderState.PENDING_PAYMENT).target(OrderState.PAID).event(OrderEvent.PAY).action(payAction).and().withExternal().source(OrderState.PAID).target(OrderState.SHIPPED).event(OrderEvent.SHIP).action(shipAction).and().withExternal().source(OrderState.SHIPPED).target(OrderState.COMPLETED).event(OrderEvent.DELIVER).action(deliverAction);}// 其他配置方法保持不變
}

在這個擴展示例中,通過定義?Action?對象,并在狀態轉移規則中使用?action()?方法,在狀態轉移時執行了相應的操作。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/72130.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/72130.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/72130.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數組總和 (leetcode 40

leetcode系列 文章目錄 一、核心操作二、外層配合操作三、核心模式代碼總結 去重方式和之前三數之和一樣&#xff0c;也可以用used數組去重&#xff0c;但本次嘗試使用set去重 一、核心操作 如果count為0了&#xff0c;則證明正好減到了0&#xff0c;就可以收獲&#xff0c;…

sqli-lab靶場學習(八)——Less26-28

前言 25關已經出現了初步的一些關鍵字過濾&#xff0c;通過雙寫可以繞過。后面的關卡&#xff0c;我們會遇到更多關鍵字過濾&#xff0c;需要各種技巧繞過。 Less26 第26關寫了會過濾空格和注釋符。有很多的答案&#xff0c;會用%a0替代空格&#xff0c;但據說這是sqli-labs部…

python:VOC格式數據集轉換為YOLO數據集格式

作者&#xff1a;CSDN _養樂多_ 本文將介紹如何將目標檢測中常用的VOC格式數據集轉換為YOLO數據集&#xff0c;并進行數據集比例劃分&#xff0c;從而方便的進行YOLO目標檢測。 如果不想分兩步&#xff0c;可以直接看第三節代碼。 文章目錄 一、將VOC格式數據集轉換為YOLO格…

Docker容器安裝軟件(完整版)

文章目錄 一、安裝Docker1.1 docker 相關的命令1.2 配置鏡像加速 二. 安裝es2.1 創建網絡2.2 拉取鏡像2.3 創建掛載點目錄2.4 部署單點es&#xff0c;創建es容器2.5 編寫elasticsearch.yml2.6 重啟es容器2.7 測試Elasticsearch是否安裝成功 三. 基于Docker安裝Kibana3.1 拉取鏡…

LINUX 指令大全

Linux服務器上有許多常用的命令&#xff0c;可以幫助你管理文件、目錄、進程、網絡和系統配置等。以下是一些常用的Linux命令&#xff1a; 文件和目錄管理 ls&#xff1a;列出當前目錄中的文件和子目錄 bash lspwd&#xff1a;顯示當前工作目錄的路徑 bash pwdcd&#xff1a;切…

燃氣對我們生活的重要性體現在哪里?

燃氣在我們的生活中有 多方面的重要性 &#xff0c;以下是燃氣對我們生活的重要性的詳細說明&#xff1a; 烹飪和熱水供應 &#xff1a; 燃氣是家庭烹飪的主要能源&#xff0c;能夠快速、高效地加熱食物&#xff0c;使家庭聚餐更加便捷和愉快。 燃氣熱水器能夠在短時間內提供…

NetAssist 5.0.14網絡助手基礎使用及自動應答使用方案

以下是NetAssist v5.0.14自動應答功能的詳細使用步驟&#xff1a; 一、基礎準備&#xff1a; 工具下載網址頁面&#xff1a;https://www.cmsoft.cn/resource/102.html 下載安裝好后&#xff0c;根據需要可以創建多個server&#xff0c;雙擊程序圖標運行即可&#xff0c;下面…

node.js-node.js作為服務器,前端使用WebSocket(單個TCP連接上進行全雙工通訊的協議)

1.WebSocket全雙工通信協議 WebSocket是HTML5開始提供的一種單個TCP連接上進行全雙工通訊的協議。讓客戶端和服務器間的數據交互變得簡單&#xff0c;允許服務端向客戶端主動推送數據。瀏覽器和服務器間只需要完成一次握手&#xff0c;兩者間創建持久性的連接&#xff0c;并進行…

java后端開發day31--集合進階(一)-----Collection集合List集合數據結構1

&#xff08;以下內容全部來自上述課程&#xff09; 1.集合體系結構 List系列集合&#xff1a;添加的元素是有序、可重復、有索引。 Set系列集合&#xff1a;添加的元素是無序、不重復、無索引。 2.Collection集合 Collection是單列集合的祖宗接口&#xff08;不可直接創建…

Qt配置OpenGL相機踩的坑

項目根據LearnOpenGL配置Qt的相機&#xff0c;更新view矩陣和project矩陣的位移向量變得很大&#xff0c;我設置的明明相機位置是(0,0,3)&#xff0c;理想的位移向量剛好是相反數(0,0,-3)&#xff0c;對應的view矩陣位置向量可以變成(0,0,1200)…離模型非常遠矩陣模型也看不見&…

【C++設計模式】第十六篇:迭代器模式(Iterator)

注意&#xff1a;復現代碼時&#xff0c;確保 VS2022 使用 C17/20 標準以支持現代特性。 遍歷聚合對象的統一方式 1. 模式定義與用途 核心思想 ?迭代器模式&#xff1a;提供一種方法順序訪問聚合對象的元素&#xff0c;而無需暴露其內部表示。關鍵用途&#xff1a; 1.?統一…

關于WPS的Excel點擊單元格打開別的文檔的兩種方法的探究【為單元格添加超鏈接】

問題需求 目錄和文件結構如下&#xff1a; E:\Dir_Level1 │ Level1.txt │ └─Dir_Level2│ Level2.txt│ master.xlsx│└─Dir_Level3Level3.txt現在要在master.xlsx點擊單元格進而訪問Level1.txt、Level2.txt、Level3.txt這些文件。 方法一&#xff1a;“單元格右鍵…

聚類中的相似矩陣和拉普拉斯矩陣

前言&#xff08;可以略過&#xff09; 最近在看的是關于聚類的論文&#xff0c;之前對聚類的步驟和相關內容不太了解&#xff0c;為了讀懂論文就去學習了一下&#xff0c;這里將自己的理解記錄下來。學習的不全面&#xff0c;主要是為了看懂論文&#xff0c;后續如果有涉及到聚…

前端筆記 --- vue框架

目錄 基礎知識 指令的修飾符 計算屬性 watch偵聽器的寫法 Vue的生命周期 工程化開發&腳手架 VUE CLI 組件注冊的方式 scoped樣式沖突與原理 data 組件之間的關系和組件通信 v-model詳解 sync修飾符 Dom介紹 操作HTML標簽 總結 ref 和 $refs $nextTick 自…

智能雙劍合璧:基于語音識別與大模型的技術沙龍筆記整理實戰

智能雙劍合璧&#xff1a;基于語音識別與大模型的技術沙龍筆記整理實戰 ——記一次網絡安全技術沙龍的高效知識沉淀 引言&#xff1a;當網絡安全遇上AI生產力工具 在綠盟科技舉辦的"AI驅動的未來網絡安全"內部技術沙龍中&#xff0c;筆者親歷了一場關于網絡安全攻…

數據結構(藍橋杯常考點)

數據結構 前言&#xff1a;這個是針對于藍橋杯競賽常考的數據結構內容&#xff0c;基礎算法比如高精度這些會在下期給大家總結 數據結構 競賽中&#xff0c;時間復雜度不能超過10的7次方&#xff08;1秒&#xff09;到10的8次方&#xff08;2秒&#xff09; 空間限制&#x…

使用 UNIX 命令在設計中搜索標識符:vcsfind 的入門指南

在現代軟件開發和硬件設計中&#xff0c;快速準確地定位和搜索特定標識符是提高開發效率的關鍵。本文將介紹如何使用 UNIX 命令 vcsfind 在設計中搜索標識符&#xff0c;幫助您更高效地管理您的項目。 什么是 vcsfind&#xff1f; vcsfind 是一個強大的 UNIX 命令行工具&#x…

第56天:Web攻防-SQL注入增刪改查盲注延時布爾報錯有無回顯錯誤處理審計復盤

#知識點 1、Web攻防-SQL注入-操作方法&增刪改查 2、Web攻防-SQL注入-布爾&延時&報錯&盲注 一、增刪改查 1、功能&#xff1a;數據查詢 查詢&#xff1a;SELECT * FROM news where id$id 2、功能&#xff1a;新增用戶&#xff0c;添加新聞等 增加&#xff1a;IN…

跳表實現學習

1.介紹 2.源碼 跳表節點&#xff1a; /* ZSETs use a specialized version of Skiplists */ /*** brief 定義跳躍表節點的數據結構。* * 該結構體用于表示跳躍表中的一個節點&#xff0c;包含元素、分數、后向指針和多層鏈表信息。*/ typedef struct zskiplistNode {sds ele;…

Python:正則表達式

正則表達式的基礎和應用 一、正則表達式核心語法&#xff08;四大基石&#xff09; 1. ?元字符&#xff08;特殊符號&#xff09;? ?定位符 ^&#xff1a;匹配字符串開始位置 $&#xff1a;匹配字符串結束位置 \b&#xff1a;匹配單詞邊界?&#xff08;如 \bword\b 匹配…