背景介绍
本系列通过学习SpringStateMachine中附带的10余个Sample来学习SpringStateMachine中的各个概念和用法。项目是使用的分支为2.2.0.RELEASE[1]。项目参考文档也是2.2.0.RELEASE[1]。
TURN STILE简介
turnstile是对体育场入口或地铁入口的旋转栅门构建的状态机。
状态机的两种状态:
- LOCKED
- UNLOCKED
状态机的两种事件
- COIN
- PUSH
触发相应事件后发生状态转换。

讯享网
TURN STILE 依赖
项目在实现上述功能时,需要依赖springshell,官方给出的demo[4]使用了spring-shell1.2,本文将其改为spring-shell 2.0.0.RELEASE。
<dependency> <groupId>org.springframework.statemachine</groupId> <artifactId>spring-statemachine-core</artifactId> <version>2.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.shell</groupId> <artifactId>spring-shell-starter</artifactId> <version>2.0.0.RELEASE</version> </dependency>
讯享网
TURN STILE 实现
为了实现本例,我们需要描述状态及其转换。首先定义状态与事件枚举类型。
状态枚举类型:
讯享网public enum States {
LOCKED, UNLOCKED }
使状态发生变化的事件枚举类型:
public enum Events {
COIN, PUSH }
接着我们配置状态与转换。

讯享网package springboot.statemachine.example.turnstile.demo; import org.springframework.context.annotation.Configuration; import org.springframework.statemachine.config.EnableStateMachine; import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter; 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> {
@Override public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {
states .withStates() .initial(States.LOCKED) .states(EnumSet.allOf(States.class)); } @Override public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {
transitions .withExternal() .source(States.LOCKED) .target(States.UNLOCKED) .event(Events.COIN) .and() .withExternal() .source(States.UNLOCKED) .target(States.LOCKED) .event(Events.PUSH); } }
在配置状态与转换时用到如下的注解与类:
- @Configuration
- @EnableStateMachine
- EnumStateMachineConfigurerAdapter
代码继承EnumStateMachineConfigurerAdapter类,并覆盖两个configure方法,在这两个方法中分别来配置转换与状态列表同时指定好初始状态。
随后在创建的类上增加@EnableStateMachine与@Configuration注解,通过这些创建状态机实例,系统随后会检测是否使用了adapter类,并在运行时根据这些配置修改状态机。
最后是命令实现。这里对StateMachineCommands官方demo[5]进行了小修改。最后通过stateMachine的sendEvent方法发送事件,使状态机状态发生变化。
import org.springframework.shell.standard.ShellComponent; import org.springframework.shell.standard.ShellMethod; import springboot.statemachine.example.AbstractStateMachineCommands; @ShellComponent public class StateMachineCommands extends AbstractStateMachineCommands<States, Events> {
@ShellMethod(key = "sm event", value = "Sends an event to a state machine") public String event(Events event) {
getStateMachine().sendEvent(event); return "Event " + event + " send"; } }
此外将官方AbstractStateMachineCommands[6]中打印turn stile字符图形的部分去掉了。
讯享网import org.springframework.beans.factory.annotation.Autowired; import org.springframework.shell.standard.ShellMethod; import org.springframework.statemachine.StateMachine; import org.springframework.statemachine.state.State; import org.springframework.util.StringUtils; import java.util.Iterator; import java.util.Map.Entry; import java.util.Set; public class AbstractStateMachineCommands<S, E>{
@Autowired private StateMachine<S, E> stateMachine; protected StateMachine<S, E> getStateMachine() {
return stateMachine; } @ShellMethod(key = "sm state", value = "Prints current state") public String state() {
State<S, E> state = stateMachine.getState(); if (state != null) {
return StringUtils.collectionToCommaDelimitedString(state.getIds()); } else {
return "No state"; } } @ShellMethod(key = "sm start", value = "Start a state machine") public String start() {
stateMachine.start(); return "State machine started"; } @ShellMethod(key = "sm stop", value = "Stop a state machine") public String stop() {
stateMachine.stop(); return "State machine stopped"; } @ShellMethod(key = "sm variables", value = "Prints extended state variables") public String variables() {
StringBuilder buf = new StringBuilder(); Set<Entry<Object, Object>> entrySet = stateMachine.getExtendedState().getVariables().entrySet(); Iterator<Entry<Object, Object>> iterator = entrySet.iterator(); if (entrySet.size() > 0) {
while (iterator.hasNext()) {
Entry<Object, Object> e = iterator.next(); buf.append(e.getKey() + "=" + e.getValue()); if (iterator.hasNext()) {
buf.append("\n"); } } } else {
buf.append("No variables"); } return buf.toString(); } }
验证
发送不同的命令触发事件,并查看状态机当前状态,发现状态正确发生变化。
State machine started shell:>sm event COIN Event COIN send shell:>sm event PUSH Event PUSH send shell:>sm start State machine started shell:>sm state LOCKED shell:>sm event COIN Event COIN send shell:>sm state UNLOCKED shell:>sm event PUSH Event PUSH send shell:>sm state LOCKED shell:>sm event PUSH Event PUSH send shell:>sm state LOCKED shell:>sm state COIN LOCKED shell:>sm state LOCKED shell:>sm start State machine started shell:>sm state LOCKED shell:>sm stop
总结
通过turnstile这个例子学习了基础的概念及相关配置。通过
- @Configuration,
- @EnableStateMachine,
- EnumStateMachineConfigurerAdapter
完成配置及创建单实例。实现触发事件使状态机当前状态发生变化,从源状态到目标状态变化。
参考
[1]2.2.0.RELEASE source,https://github.com/spring-projects/spring-statemachine/blob/2.2.0.RELEASE/
[2]2.2.0.RELEASE/reference,https://docs.spring.io/spring-statemachine/docs/2.2.0.RELEASE/reference
[3]turnstile,https://docs.spring.io/spring-statemachine/docs/2.2.0.RELEASE/reference/#statemachine-examples-turnstile
[4]turnstile demo,https://github.com/spring-projects/spring-statemachine/tree/2.2.0.RELEASE/spring-statemachine-samples/turnstile/src/main/java/demo/turnstile
[5]StateMachineCommands,https://github.com/spring-projects/spring-statemachine/blob/2.2.0.RELEASE/spring-statemachine-samples/turnstile/src/main/java/demo/turnstile/StateMachineCommands.java
[6]AbstractStateMachineCommands,https://github.com/spring-projects/spring-statemachine/blob/2.2.0.RELEASE/spring-statemachine-samples/src/main/java/demo/AbstractStateMachineCommands.java
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/52147.html