diff --git a/solon-projects/solon-base/solon-statemachine/NOTICE b/solon-projects/solon-base/solon-statemachine/NOTICE
new file mode 100644
index 0000000000000000000000000000000000000000..0a7dd15facdb99fca5e29ee9aa2246fcd52d170c
--- /dev/null
+++ b/solon-projects/solon-base/solon-statemachine/NOTICE
@@ -0,0 +1,28 @@
+Copyright 2017-2025 noear.org and authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+This project includes:
+ asm under BSD-3-Clause
+ JUnit Jupiter (Aggregator) under Eclipse Public License v2.0
+ JUnit Jupiter API under Eclipse Public License v2.0
+ JUnit Jupiter Engine under Eclipse Public License v2.0
+ JUnit Jupiter Params under Eclipse Public License v2.0
+ JUnit Platform Commons under Eclipse Public License v2.0
+ JUnit Platform Engine API under Eclipse Public License v2.0
+ org.apiguardian:apiguardian-api under The Apache License, Version 2.0
+ org.opentest4j:opentest4j under The Apache License, Version 2.0
+ SLF4J API Module under MIT License
+ solon under The Apache Software License, Version 2.0
+ solon-proxy under The Apache Software License, Version 2.0
+
diff --git a/solon-projects/solon-base/solon-statemachine/pom.xml b/solon-projects/solon-base/solon-statemachine/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..aa7147009cfe76562bef4b22ed76829d4600c066
--- /dev/null
+++ b/solon-projects/solon-base/solon-statemachine/pom.xml
@@ -0,0 +1,31 @@
+
+
+ 4.0.0
+
+
+ org.noear
+ solon-parent
+ 3.4.2
+ ../../../solon-parent/pom.xml
+
+
+ solon-statemachine
+ ${project.artifactId}
+ jar
+
+
+
+ org.noear
+ solon
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ ${junit5.version}
+ test
+
+
+
\ No newline at end of file
diff --git a/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/Event.java b/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/Event.java
new file mode 100644
index 0000000000000000000000000000000000000000..114fb370a9e0368983b5c1fc7514faac0e98bc77
--- /dev/null
+++ b/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/Event.java
@@ -0,0 +1,7 @@
+package org.noear.solon.statemachine;
+
+/**
+ * 事件接口
+ */
+public interface Event {
+}
\ No newline at end of file
diff --git a/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/State.java b/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/State.java
new file mode 100644
index 0000000000000000000000000000000000000000..998cf31e1b08772eda4099f6b431f837e17c95f8
--- /dev/null
+++ b/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/State.java
@@ -0,0 +1,7 @@
+package org.noear.solon.statemachine;
+
+/**
+ * 状态接口
+ */
+public interface State {
+}
\ No newline at end of file
diff --git a/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/StateContext.java b/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/StateContext.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7b7b1c87a395ddbba773de32ab367e8870d74be
--- /dev/null
+++ b/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/StateContext.java
@@ -0,0 +1,36 @@
+package org.noear.solon.statemachine;
+
+/**
+ * 状态机上下文,保存状态转换相关信息
+ */
+public class StateContext {
+ private final S from;
+ private final S to;
+ private final E event;
+ private final T payload;
+
+ public StateContext(S from, S to, E event, T payload) {
+ this.from = from;
+ this.to = to;
+ this.event = event;
+ this.payload = payload;
+ }
+
+ public S getFrom() {
+ return from;
+ }
+
+ public S getTo() {
+ return to;
+ }
+
+ public E getEvent() {
+ return event;
+ }
+
+
+ public T getPayload() {
+ return payload;
+ }
+
+}
\ No newline at end of file
diff --git a/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/StateMachine.java b/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/StateMachine.java
new file mode 100644
index 0000000000000000000000000000000000000000..c9fc4eaa1da3e368ee560dd5498b614389111d62
--- /dev/null
+++ b/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/StateMachine.java
@@ -0,0 +1,50 @@
+package org.noear.solon.statemachine;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class StateMachine {
+ /**
+ * 当前状态
+ */
+ private S currentState;
+
+ private final List> transitions = new ArrayList<>();
+
+ public StateMachine(S initState) {
+ this.currentState = initState;
+ }
+
+ /**
+ * 添加状态转换规则
+ */
+ public void addTransition(StateTransition transition) {
+ transitions.add(transition);
+ }
+
+ public synchronized boolean execute(E event, T payload) {
+ for (StateTransition transition : transitions) {
+ if (transition.matches(currentState, event, payload)) {
+ S from = currentState;
+ S to = transition.getTo();
+ currentState = to;
+ transition.execute(new StateContext<>(from, to, event, payload));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public synchronized boolean execute(E event) {
+ return execute(event, null);
+
+ }
+
+ public S getCurrentState() {
+ return currentState;
+ }
+
+ public void restore(S state) {
+ this.currentState = state;
+ }
+}
\ No newline at end of file
diff --git a/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/StateTransition.java b/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/StateTransition.java
new file mode 100644
index 0000000000000000000000000000000000000000..582ac214a53e7ec3a0ad0026a7c58cb9049d90ae
--- /dev/null
+++ b/solon-projects/solon-base/solon-statemachine/src/main/java/org/noear/solon/statemachine/StateTransition.java
@@ -0,0 +1,55 @@
+package org.noear.solon.statemachine;
+
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+
+/**
+ * 状态转换定义
+ */
+public class StateTransition {
+ private final S from;
+ private final S to;
+ private final E event;
+
+ private final BiPredicate, T> condition;
+ private final Consumer> action;
+
+ public StateTransition(S from, S to, E event) {
+ this(from, to, event, (ctx, payload) -> true, (ctx) -> {
+ });
+ }
+
+ public StateTransition(S from, S to, E event, Consumer> action) {
+ this(from, to, event, (ctx, payload) -> true, action);
+ }
+
+ public StateTransition(S from, S to, E event, BiPredicate, T> condition, Consumer> action) {
+ this.from = from;
+ this.to = to;
+ this.event = event;
+ this.condition = condition;
+ this.action = action;
+ }
+
+
+ public S getFrom() {
+ return from;
+ }
+
+ public S getTo() {
+ return to;
+ }
+
+ public E getEvent() {
+ return event;
+ }
+
+ public boolean matches(S state, E event, T payload) {
+ return from.equals(state) && this.event.equals(event) && condition.test(new StateContext<>(from, to, event, payload), payload);
+ }
+
+ public void execute(StateContext context) {
+ action.accept(context);
+ }
+
+}
\ No newline at end of file
diff --git a/solon-projects/solon-base/solon-statemachine/src/test/java/test1/App.java b/solon-projects/solon-base/solon-statemachine/src/test/java/test1/App.java
new file mode 100644
index 0000000000000000000000000000000000000000..08979ea02664bd47d67effb502ee009414e651cb
--- /dev/null
+++ b/solon-projects/solon-base/solon-statemachine/src/test/java/test1/App.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2017-2025 noear.org and authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test1;
+
+
+import org.junit.jupiter.api.Test;
+import org.noear.solon.statemachine.StateMachine;
+import org.noear.solon.statemachine.StateTransition;
+import test1.enums.OrderEvent;
+import test1.enums.OrderState;
+
+public class App {
+ @Test
+ public void test() {
+ // 创建状态机实例
+ StateMachine stateMachine = new StateMachine<>(OrderState.NONE);
+
+ // 无 -> 创建订单
+ stateMachine.addTransition(new StateTransition<>(OrderState.NONE, OrderState.CREATED, OrderEvent.CREATE,
+ (order) -> {
+ Order payload = order.getPayload();
+ payload.setStatus("已创建");
+ System.out.println(payload);
+ }
+ ));
+
+ // 创建 -> 支付
+ stateMachine.addTransition(new StateTransition<>(OrderState.CREATED, OrderState.PAID, OrderEvent.PAY,
+ (order) -> {
+ Order payload = order.getPayload();
+ payload.setStatus("已支付");
+ System.out.println(payload);
+ }
+ ));
+
+ // 支付 -> 发货
+ stateMachine.addTransition(new StateTransition<>(OrderState.PAID, OrderState.SHIPPED, OrderEvent.SHIP,
+ (order) -> {
+ Order payload = order.getPayload();
+ payload.setStatus("已发货");
+ System.out.println(payload);
+ }
+ ));
+
+
+ // 发货 -> 送达
+ stateMachine.addTransition(new StateTransition<>(OrderState.SHIPPED, OrderState.DELIVERED, OrderEvent.DELIVER,
+ (order) -> {
+ Order payload = order.getPayload();
+ payload.setStatus("已送达");
+ System.out.println(payload);
+ }
+ ));
+
+ Order order = new Order("1", "iphone16 pro max", null);
+
+ stateMachine.execute(OrderEvent.CREATE, order);
+ stateMachine.execute(OrderEvent.PAY, order);
+ stateMachine.execute(OrderEvent.SHIP, order);
+ stateMachine.execute(OrderEvent.DELIVER, order);
+ }
+}
\ No newline at end of file
diff --git a/solon-projects/solon-base/solon-statemachine/src/test/java/test1/Order.java b/solon-projects/solon-base/solon-statemachine/src/test/java/test1/Order.java
new file mode 100644
index 0000000000000000000000000000000000000000..b1a281498717b7a171bdd7ffdedaeda6ea7c8bb4
--- /dev/null
+++ b/solon-projects/solon-base/solon-statemachine/src/test/java/test1/Order.java
@@ -0,0 +1,49 @@
+package test1;
+
+public class Order {
+ private String id;
+ private String productName;
+ private String status;
+
+ public Order(String id, String productName, String status) {
+ this.id = id;
+ this.productName = productName;
+ this.status = status;
+ }
+
+ public Order() {
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getProductName() {
+ return productName;
+ }
+
+ public void setProductName(String productName) {
+ this.productName = productName;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ @Override
+ public String toString() {
+ return "Order{" +
+ "id='" + id + '\'' +
+ ", productName='" + productName + '\'' +
+ ", status='" + status + '\'' +
+ '}';
+ }
+}
diff --git a/solon-projects/solon-base/solon-statemachine/src/test/java/test1/enums/OrderEvent.java b/solon-projects/solon-base/solon-statemachine/src/test/java/test1/enums/OrderEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..bca6be4a1e661c44813213ad6894866a388fd3e9
--- /dev/null
+++ b/solon-projects/solon-base/solon-statemachine/src/test/java/test1/enums/OrderEvent.java
@@ -0,0 +1,11 @@
+package test1.enums;
+
+
+import org.noear.solon.statemachine.Event;
+
+/**
+ * 订单事件枚举
+ */
+public enum OrderEvent implements Event {
+ CREATE, PAY, SHIP, DELIVER, CANCEL;
+}
\ No newline at end of file
diff --git a/solon-projects/solon-base/solon-statemachine/src/test/java/test1/enums/OrderState.java b/solon-projects/solon-base/solon-statemachine/src/test/java/test1/enums/OrderState.java
new file mode 100644
index 0000000000000000000000000000000000000000..2665fc2f5447eba3a65e7f170440caf296bbfa66
--- /dev/null
+++ b/solon-projects/solon-base/solon-statemachine/src/test/java/test1/enums/OrderState.java
@@ -0,0 +1,11 @@
+package test1.enums;
+
+
+import org.noear.solon.statemachine.State;
+
+/**
+ * 订单状态枚举
+ */
+public enum OrderState implements State {
+ NONE,CREATED, PAID, SHIPPED, DELIVERED, CANCELLED;
+}
\ No newline at end of file