博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(spring全家桶十)Spring Statemachine有限状态机与地址分析
阅读量:5740 次
发布时间:2019-06-18

本文共 10767 字,大约阅读时间需要 35 分钟。

一、有限状态机

有限状态机是一个特殊的有向图,包含节点和连接这些节点的弧。每个有限状态机都有开始、结束和若干个中间状态,每个弧上带有从一个状态进入下一个状态的条件。

以一个简化的购物流程为例,开始和结束之间有待下单、待支付、待发货、待收货四个状态,从一个状态转向另外一个状态中间需要发送事件。

这里写图片描述

有限状态机可以用于中文地址分析,识别地址的有限状态机如下。

这里写图片描述

给出一个地址,如果当前状态是“省”,后面一个词组是二级市,就进入状态“市”;如果下一个词组是某某区或者某某县,就进入“区县”状态。

如果一个地址能从状态机的开始状态经过若干中间状态到达终止状态,地址有效,否则地址无效。

例如:北京市海淀区清华东路17号,有效。河北省大连市友好路,无效。

二、Spring Statemachine

是spring的有限状态机开源框架,诞生不久。

Spring Statemachine框架的目标:

1.简单易用
2.采用层次化状态机结构简化复杂状态配置
3.State machine regions提供复杂的状态机配置
4.使用triggers, transitions, guards and actions.
5.类型安全的适配器配置
6.用于Spring应用程序上下文之外的简单实例化的生成器模式
7.基于ZooKeeper实现的分布式状态机
8.有事件监听器
9.在持久层存储状态配置
10.Spring IOC集成,bean可以和状态机交互

三、实例

3.1 创建spring boot工程

访问: ,新建一个spring boot工程:

这里写图片描述

pom.xml:

4.0.0
com.statemachine
statemachinedemo
0.0.1-SNAPSHOT
jar
statemachinedemo
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
1.5.7.RELEASE
UTF-8
UTF-8
1.8
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
org.springframework.statemachine
spring-statemachine-core
1.2.6.RELEASE
log4j
log4j
1.2.17
org.springframework.boot
spring-boot-maven-plugin

创建状态:

public enum States {    START,     //开始    PROVINCE,  //省    CITY,      //市    DISTRIC,    //区县    STREET,     //街道    STREET_NUM,  //街道号}

定义事件:

public enum Events {    HAS_PROVINCE,    //地址中有一级省份    HAS_CITY,        //地址中有二级市    HAS_DISTRIC,     //地址中有三级县或者区    HAS_STREET,      //地址中有四级的街道    HAS_STREET_NUM   //地址中有五级的街道号}

设置状态之间的转换关系:

import com.sun.org.apache.regexp.internal.RE;import org.apache.log4j.Logger;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 org.springframework.statemachine.listener.StateMachineListener;import org.springframework.statemachine.listener.StateMachineListenerAdapter;import org.springframework.statemachine.transition.Transition;import java.util.EnumSet;@Configuration@EnableStateMachinepublic class Config extends EnumStateMachineConfigurerAdapter
{ public static final Logger logger = Logger.getLogger(Config.class); @Override public void configure(StateMachineStateConfigurer
states) throws Exception { states .withStates() .initial(States.START) .states(EnumSet.allOf(States.class)); } @Override public void configure(StateMachineTransitionConfigurer
transitions) throws Exception { transitions .withExternal().source(States.START).target(States.PROVINCE).event(Events.HAS_PROVINCE) .and() .withExternal().source(States.START).target(States.CITY).event(Events.HAS_CITY) .and() .withExternal().source(States.PROVINCE).target(States.CITY).event(Events.HAS_CITY) .and() .withExternal().source(States.PROVINCE).target(States.DISTRIC).event(Events.HAS_DISTRIC) .and() .withExternal().source(States.CITY).target(States.STREET).event(Events.HAS_STREET) .and() .withExternal().source(States.STREET).target(States.STREET_NUM).event(Events.HAS_STREET_NUM); } public StateMachineListener
listener() { return new StateMachineListenerAdapter
() { @Override public void transition(Transition
transition) { if (transition.getTarget().getId() == States.START) { logger.info("开始:"); return; } if (transition.getSource().getId() == States.START && transition.getTarget().getId() == States.PROVINCE) { logger.info("省份:"); return; } if (transition.getSource().getId() == States.START && transition.getTarget().getId() == States.CITY) { logger.info("市:"); return; } if (transition.getSource().getId() == States.PROVINCE && transition.getTarget().getId() == States.CITY) { logger.info("市:"); return; } if (transition.getSource().getId() == States.PROVINCE && transition.getTarget().getId() == States.DISTRIC) { logger.info("县:"); return; } if (transition.getSource().getId() == States.CITY && transition.getTarget().getId() == States.STREET) { logger.info("街道:"); return; } if (transition.getSource().getId() == States.DISTRIC && transition.getTarget().getId() == States.STREET) { logger.info("街道:"); return; } if (transition.getSource().getId() == States.STREET && transition.getTarget().getId() == States.STREET_NUM) { logger.info("街道号:"); return; } } }; } @Override public void configure(StateMachineConfigurationConfigurer
config) throws Exception { config.withConfiguration().listener(listener()); }}

运行:

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;@SpringBootApplicationpublic class Application implements CommandLineRunner {
public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Autowired private StateMachine
stateMachine; @Override public void run(String... args) throws Exception { stateMachine.start(); stateMachine.sendEvent(Events.HAS_PROVINCE); stateMachine.sendEvent(Events.HAS_CITY); stateMachine.sendEvent(Events.HAS_STREET); stateMachine.sendEvent(Events.HAS_STREET_NUM); }}

结果:

.   ____          _            __ _ _ /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/  ___)| |_)| | | | | || (_| |  ) ) ) )  '  |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot ::        (v1.5.6.RELEASE)2017-09-23 17:55:27.787  INFO 9344 --- [           main] xtipc.statemachine.addr.Application      : Starting Application on elk-PC with PID 9344 (E:\CODE\statemachinedemo\target\classes started by elk in E:\CODE\statemachinedemo)2017-09-23 17:55:27.790  INFO 9344 --- [           main] xtipc.statemachine.addr.Application      : No active profile set, falling back to default profiles: default2017-09-23 17:55:27.864  INFO 9344 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5fdba6f9: startup date [Sat Sep 23 17:55:27 CST 2017]; root of context hierarchy2017-09-23 17:55:28.565  INFO 9344 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.statemachine.config.configuration.StateMachineAnnotationPostProcessorConfiguration' of type [org.springframework.statemachine.config.configuration.StateMachineAnnotationPostProcessorConfiguration$$EnhancerBySpringCGLIB$$3d777845] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)2017-09-23 17:55:29.075  INFO 9344 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup2017-09-23 17:55:29.079  INFO 9344 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 02017-09-23 17:55:29.089  INFO 9344 --- [           main] xtipc.statemachine.addr.Config           : 开始:2017-09-23 17:55:29.092  INFO 9344 --- [           main] o.s.s.support.LifecycleObjectSupport     : started org.springframework.statemachine.support.DefaultStateMachineExecutor@77102b912017-09-23 17:55:29.092  INFO 9344 --- [           main] o.s.s.support.LifecycleObjectSupport     : started CITY PROVINCE END DISTRIC STREET_NUM STREET START  / START / uuid=868923f4-239a-4730-ae7b-f71753876f3a / id=null2017-09-23 17:55:29.097  INFO 9344 --- [           main] xtipc.statemachine.addr.Config           : 省份:2017-09-23 17:55:29.098  INFO 9344 --- [           main] xtipc.statemachine.addr.Config           : 市:2017-09-23 17:55:29.098  INFO 9344 --- [           main] xtipc.statemachine.addr.Config           : 街道:2017-09-23 17:55:29.098  INFO 9344 --- [           main] xtipc.statemachine.addr.Config           : 街道号:2017-09-23 17:55:29.099  INFO 9344 --- [           main] xtipc.statemachine.addr.Application      : Started Application in 1.655 seconds (JVM running for 2.133)2017-09-23 17:55:29.100  INFO 9344 --- [       Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@5fdba6f9: startup date [Sat Sep 23 17:55:27 CST 2017]; root of context hierarchy2017-09-23 17:55:29.101  INFO 9344 --- [       Thread-2] o.s.c.support.DefaultLifecycleProcessor  : Stopping beans in phase 02017-09-23 17:55:29.102  INFO 9344 --- [       Thread-2] o.s.s.support.LifecycleObjectSupport     : stopped org.springframework.statemachine.support.DefaultStateMachineExecutor@77102b912017-09-23 17:55:29.102  INFO 9344 --- [       Thread-2] o.s.s.support.LifecycleObjectSupport     : stopped CITY PROVINCE END DISTRIC STREET_NUM STREET START  /  / uuid=868923f4-239a-4730-ae7b-f71753876f3a / id=null2017-09-23 17:55:29.103  INFO 9344 --- [       Thread-2] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown2017-09-23 17:55:29.112  INFO 9344 --- [       Thread-2] o.s.s.support.LifecycleObjectSupport     : destroy called
你可能感兴趣的文章
矩阵的行列式的计算-余子式
查看>>
A.Activity planning
查看>>
新闻发布项目——业务逻辑层(newsTbServiceImpl)
查看>>
N!分解素因子及若干问题【转载】
查看>>
在Apache Tomcat 7设置redis作为session store
查看>>
Linkin大话eclipse快捷键
查看>>
二分图的最大匹配 (匈牙利算法)
查看>>
cocos2dx-3.0(21) 移植android平台 说多了都是泪
查看>>
Hadoop学习笔记(四)Hadoop伪分布式配置
查看>>
有限自动机的构造与识别
查看>>
RedHat Linux 安装oracle11g (转)
查看>>
清除浮动的方法以及各自的优缺点
查看>>
android 模块编译,mm 命令
查看>>
Linux内存初始化(二)identity mapping和kernel image mapping
查看>>
chmod -x chmod的N种解法
查看>>
41、生鲜电商平台-物流动态费率、免运费和固定运费设计与架构
查看>>
autoit获取ie浏览器简单操作网页(GUI小工具)
查看>>
for...in 和 for each...in的一些区分和用法
查看>>
多项式输出
查看>>
转载:性能优化——统计信息——SQLServer自动更新和自动创建统计信息选项
查看>>