Appearance
Spring 状态机
依赖
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-data-redis</artifactId>
<version>4.0.1</version>
</dependency>
</dependencies>枚举类
状态枚举类 States
java
public enum States {
SI, S1, S2
}事件枚举类 Events
java
public enum Events {
E1, E2
}配置类
StateMachineExample01Config
java
@Configuration
@EnableStateMachine(name = "stateMachineExample01")
public class StateMachineExample01Config extends EnumStateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineConfigurationConfigurer<States, Events> config) throws Exception {
// 配置状态机自动启动,同时设置了监听器,该监听器的作用用来监听状态的变化
config.withConfiguration().autoStartup(true).listener(example01Listener());
}
@Override
public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {
// 定义了初始化状态,及所有的状态
states.withStates().initial(States.SI).states(EnumSet.allOf(States.class));
}
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {
// 配置状态的转换,如下面从SI状态转化到S1状态需要通过E1事件
transitions
.withExternal().source(States.SI).target(States.S1).event(Events.E1)
.and()
.withExternal().source(States.S1).target(States.S2).event(Events.E2);
}
// 监听程序,监听状态的改变
@Bean
StateMachineListener<States, Events> example01Listener() {
return new StateMachineListenerAdapter<States, Events>() {
@Override
public void stateChanged(State<States, Events> from, State<States, Events> to) {
System.out.println("Example01 状态切换至 " + to.getId());
}
};
}
}控制器类
Example01Controller
java
@RestController
@RequestMapping("/example01")
public class Example01Controller {
// 这里指定了注入的bean名称,因为项目中你可以定义多个不同的状态机
@Resource(name = "stateMachineExample01")
private StateMachine<States, Events> stateMachine;
@GetMapping("/s1")
public Object changeToS1() {
Message<Events> message = MessageBuilder.withPayload(Events.E1).build();
stateMachine.sendEvent(Mono.just(message)).subscribe();
return "将状态切换到 S1";
}
@GetMapping("/s2")
public Object changeToS2() {
Message<Events> message = MessageBuilder.withPayload(Events.E2).build();
stateMachine.sendEvent(Mono.just(message)).subscribe();
return "将状态切换到 S2";
}
// 查看当前的状态
@GetMapping("/state")
public Object getState() {
State<States, Events> state = stateMachine.getState();
return state.getId();
}
}进阶
为状态切换添加 Action
java
@Override
public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {
states.withStates()
.initial(States.SI) // 设置初始状态为 SI
// 进入 S1 状态时触发(已到达 S1)
.stateEntry(States.S1, context -> {
System.out.printf("准备从 %s 状态转换到 %s%n", context.getSource().getId(), context.getTarget().getId());
})
// 处于 S1 状态时触发(已处于 S1)
.state(States.S1, context -> {
System.out.printf("状态从 %s 状态转换到 %s%n", context.getSource().getId(), context.getTarget().getId());
})
// 离开 S1 状态时触发(即将离开 S1)
.stateExit(States.S1, context -> {
System.out.printf("状态从 %s 状态转换到 %s%n", context.getSource().getId(), context.getTarget().getId());
})
// 处于 S2 状态时触发(已处于 S2)
.state(States.S2, context -> {
System.out.printf("状态从 %s 状态转换到 %s%n", context.getSource().getId(), context.getTarget().getId());
});
}输出结果
java
// 1.启动应用程序
Example01 状态切换至 SI
// 2.访问 /example01/s1
准备从 SI 状态转换到 S1
Example01 状态切换至 S1
状态从 SI 状态转换到 S1
// 3.访问 /example01/s2
状态从 S1 状态转换到 S2
Example01 状态切换至 S2
状态从 S1 状态转换到 S2持久化
持久化配置 (redis)
java
@Configuration
public class StateMachinePersisterConfig {
@Bean
RedisStateMachinePersister<States, Events> repositoryStateMachinePersist(RedisConnectionFactory redisConnectionFactory) {
RedisStateMachineContextRepository<States, Events> stateMachineContextRepository = new RedisStateMachineContextRepository<>(redisConnectionFactory);
StateMachinePersist<States, Events, String> repositoryStateMachinePersist = new RepositoryStateMachinePersist<States, Events>(stateMachineContextRepository);
return new RedisStateMachinePersister<States, Events>(repositoryStateMachinePersist);
}
}状态机配置
java
@Configuration
@EnableStateMachine(name = "stateMachineExample")
public class StateMachineExampleConfig extends EnumStateMachineConfigurerAdapter<States, Events> {
@Resource
private ApplicationContext context;
@Resource
private RedisStateMachinePersister<States, Events> repositoryStateMachinePersist;
@Override
public void configure(StateMachineConfigurationConfigurer<States, Events> config) throws Exception {
config.withConfiguration().autoStartup(true).listener(exampleListener());
}
@Override
public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {
states.withStates().initial(States.SI).states(EnumSet.allOf(States.class));
}
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {
transitions
.withExternal().source(States.SI).target(States.S1).event(Events.E1)
.and()
.withExternal().source(States.S1).target(States.S2).event(Events.E2);
}
@Bean
StateMachineListener<States, Events> exampleListener() {
return new StateMachineListenerAdapter<States, Events>() {
@Override
public void stateChanged(State<States, Events> from, State<States, Events> to) {
try {
// 初始状态不做保存,只有状态发生切换后,才进行持久化操作
if (from != null) {
repositoryStateMachinePersist.persist(
(StateMachine<States, Events>) context.getBean("stateMachineExample"),
"s000"
);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
}
}数据恢复配置
java
@Component
public class StatePersistComponent {
@Resource
private RedisStateMachinePersister<States, Events> persist; // 状态机持久化工具(Redis
@Resource(name = "stateMachineExample")
private StateMachine<States, Events> stateMachineExample; // 状态机实例
@PostConstruct
public void init() {
try {
this.persist.restore(stateMachineExample, "s000"); // 从Redis恢复状态
} catch (Exception e) {
e.printStackTrace();
}
}
}多上下文
基于内存
java
@Bean(name = "memoryPersisiter")
static StateMachinePersister<States, Events, Object> getMemoryPersisiter() {
return new DefaultStateMachinePersister<>(
new StateMachinePersist<States, Events, Object>() {
private Map<Object, StateMachineContext<States, Events>> map = new HashMap<>();
@Override
public void write(StateMachineContext<States, Events> context, Object contextObj) throws Exception {
log.info("持久状态机, context: {}, contextObj: {}", context, new ObjectMapper().writeValueAsString(contextObj));
map.put(contextObj, context);
}
@Override
public StateMachineContext<States, Events> read(Object contextObj) throws Exception {
log.info("获取状态机, contextObj: {}", new ObjectMapper().writeValueAsString(contextObj));
StateMachineContext<States, Events> stateMachineContext = map.get(contextObj);
log.info("获取状态机结果, stateMachineContext: {}", new ObjectMapper().writeValueAsString(stateMachineContext));
return stateMachineContext;
}
}
);
}java
private void sendEvent(Message<Events> message, Object contextObj) {
try {
stateMachine.startReactively().block(); // 启动
this.memoryPersisiter.restore(stateMachine, contextObj); // 恢复状态
stateMachine.sendEvent(Mono.just(message)).blockLast(); // 发送事件
this.memoryPersisiter.persist(stateMachine, contextObj); // 保存状态
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
stateMachine.stopReactively().block(); // 停止
}
}更新: 2025-07-18 13:20:32
原文: https://www.yuque.com/lsxxyg/sz/wps7g4guzdg2utyl