spring 的stateMachine 相对于当前的版本,还是比较新颖的,但是对于合适的业务场景,使用起来还是十分的方便的。但是对于官网提供的文档,讲解的是十分的精简,要想更深入的了解其内部架构,只有不断的测试,查看内部源码的实现,能够大幅度的给你更大的启发!在今天,小编将介绍如何不通过使用官网的方式构建状态机,实现自己的业务逻辑:

 首先,这里为了配置方便构建,创建业务所需要的entity配置类,

    

package statemachine.v2.entity;

public class ConfigEntity {
/**
* 业务 id 号
*/
private int id;
/**
* 源状态
*/
private String source;
/**
* 目标状态
*/
private String target;
/**
* 触发的事件
*/
private String event;
/**
* 备注信息
*/
private String info; /**
* 业务类型
*/
private int type; public ConfigEntity(int id, String source, String target, String event, String info, int type) {
this.id = id;
this.source = source;
this.target = target;
this.event = event;
this.info = info;
this.type = type;
} public ConfigEntity(int id) {
this.id = id;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getSource() {
return source;
} public void setSource(String source) {
this.source = source;
} public String getTarget() {
return target;
} public void setTarget(String target) {
this.target = target;
} public String getEvent() {
return event;
} public void setEvent(String event) {
this.event = event;
} public String getInfo() {
return info;
} public void setInfo(String info) {
this.info = info;
} public int getType() {
return type;
} public void setType(int type) {
this.type = type;
} @Override
public String toString() {
return "ConfigEntity{" +
"id=" + id +
", source='" + source + '\'' +
", target='" + target + '\'' +
", event='" + event + '\'' +
", info='" + info + '\'' +
", type=" + type +
'}';
}
}

然后构建自己的配置信息类,构造相关的配置信息。

  

package statemachine.v2.config;

import org.springframework.statemachine.config.model.*;
import org.springframework.statemachine.state.PseudoStateKind;
import statemachine.v2.entity.ConfigEntity; import java.util.Arrays;
import java.util.HashSet;
import java.util.Set; /**
* 配置必要的配置信息
*/
public class SSMConfig {
private static final HashSet<String> states = new HashSet<String>();
private static final HashSet<ConfigEntity> configEntities = new HashSet<ConfigEntity>(); public static final StateData<String, String> initState = new StateData<String, String>("初始状态" ,true);
public static final StateData<String, String> endState = new StateData<String, String>("结束状态"); public static HashSet <String> getStates() {
return states;
} public static HashSet <ConfigEntity> getConfigEntities() {
return configEntities;
} /**
* 配置的构造方法
*/
static {
//构造配置信息列表,这个可以根据业务实际需求设置,可自定义
Set<ConfigEntity> configEntities = new HashSet <ConfigEntity>(Arrays.asList(
new ConfigEntity(1,"初始状态","状态1","事件1","",001),
new ConfigEntity(1,"状态1","状态2","事件2","",001),
new ConfigEntity(1,"状态2","状态1","事件3","",001),
new ConfigEntity(1,"状态2","结束状态","事件4","",001)));
for(ConfigEntity configEntity : configEntities){
states.add(configEntity.getSource());
configEntities.add(configEntity);
}
} /**
* 构建 ConfigurationData,在这一步也可以构建为分布式的,如基于zookeeper
* @return
*/
public static ConfigurationData<String,String> getConfigurationData(){
ConfigurationData<String, String> configurationData = new ConfigurationData<String, String>();
return configurationData;
} /**
* 构建状态数据信息对象, 这一步是构建状态机的各个状态字段,用于装载状态机的状态转换之间的状态配置
* @return
*/
public static StatesData<String,String> getStatesData(){
HashSet<StateData<String, String>> stateDatas = new HashSet<StateData<String, String>>();
//初始状态
initState.setPseudoStateKind(PseudoStateKind.INITIAL);
stateDatas.add(initState); //结束状态
endState.setEnd(true);
endState.setPseudoStateKind(PseudoStateKind.END);
stateDatas.add(endState); //其他状态加载
for (String state: states){
StateData<String, String> stateData = new StateData<String, String>(state);
stateDatas.add(stateData);
} //构建
StatesData<String, String> statesData = new StatesData<String, String>(stateDatas); return statesData;
} /**
* 状态事物转换的流程配置
* @return
*/
public static TransitionsData<String,String> getTransitionsData(){
HashSet<TransitionData<String,String>> transitionDatas = new HashSet<TransitionData<String,String>>();
for (ConfigEntity configEntity : configEntities ){ TransitionData<String,String> transitionData = new TransitionData<String,String>(configEntity.getSource(),
configEntity.getTarget(),
configEntity.getEvent()
);
transitionDatas.add(transitionData); }
TransitionsData<String,String> transitionsData = new TransitionsData<String,String>(transitionDatas); return transitionsData;
} }

  最后通过以上的信息,构建状态机的类,通过该类来创建状态机,获取状态机的实例:这里提供两种方式构建,大家可以根据自己的业务自行选择:

   

package statemachine.v2.config;

import org.springframework.beans.factory.support.StaticListableBeanFactory;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.ObjectStateMachineFactory;
import org.springframework.statemachine.config.StateMachineBuilder;
import org.springframework.statemachine.config.model.ConfigurationData;
import org.springframework.statemachine.config.model.DefaultStateMachineModel;
import org.springframework.statemachine.config.model.StatesData;
import org.springframework.statemachine.config.model.TransitionsData;
import statemachine.v2.entity.ConfigEntity; import java.util.Collection;
import java.util.HashSet; public class MakeStateMachine {
/**
* 构建状态机,方式一
* @return
* @throws Exception
*/
public static StateMachine<String,String> createStateMachine() throws Exception {
ConfigurationData<String, String> configData = SSMConfig.getConfigurationData();
StatesData<String, String> statesData = SSMConfig.getStatesData();
TransitionsData<String, String> transitionsData = SSMConfig.getTransitionsData();
DefaultStateMachineModel<String,String> machineModel = new DefaultStateMachineModel<String, String>(configData,statesData,transitionsData);
ObjectStateMachineFactory<String, String> machineFactory = new ObjectStateMachineFactory<String, String>(machineModel);
StateMachine<String, String> stateMachine = machineFactory.getStateMachine();
//添加状态机的监听器,自行实现
// stateMachine.addStateListener(new StateMachineListener <String, String>() {}); //添加状态机的拦截器,自行实现内部接口即可
// stateMachine.getStateMachineAccessor()
// .withRegion()
// .addStateMachineInterceptor(new StateMachineInterceptor <String, String>() {});
return stateMachine;
} /**
* 构建状态机,方式二
*/
public StateMachine<String,String> getStateMachine() throws Exception {
StateMachineBuilder.Builder<String,String> builder = StateMachineBuilder.builder();
builder.configureConfiguration()
.withConfiguration()
//添加状态机监听器
// .listener(new StateMachineListener <String, String>() {})
.beanFactory(new StaticListableBeanFactory());//添加构建bean的工厂类,可以自行实现,这里是使用系统的默认 Collection<ConfigEntity> data = SSMConfig.getConfigEntities();
HashSet<String> states = new HashSet<String>();
for (ConfigEntity configEntity : data) {
states.add(configEntity.getTarget());
builder.configureTransitions()
.withExternal()
.source(configEntity.getSource())
.target(configEntity.getTarget())
.event(configEntity.getEvent());
} builder.configureStates()
.withStates()
.initial(SSMConfig.initState.getState())
.state(SSMConfig.initState.getState())
.end(SSMConfig.endState.getState())
.states(states); return builder.build();
} }

使用的话,可以像之前的版本方式使用即可,详细可以参考:初识状态机

 

public class Main {

    public static void main(String[] args) throws Exception {

        StateMachine<String, String> stateMachine = MakeStateMachine.createStateMachine();
//方式一, 发送触发事件,改变状态
stateMachine.sendEvent("事件1"); //方式二, 发送触发事件,改变状态
stateMachine.sendEvent(MessageBuilder
.withPayload("事件1")
.setHeader("testStateMachine", "测试头部") // header中可以存放相关数据信息,
// 这些信息,在执行过程中,可以在监听器和拦截器中获取到,通过拦截器你可以在做额外的一些事情
.build()); }
}

通过spring statemmachine 自定义构建属于自己的状态机(两种方式)的更多相关文章

  1. XFire构建服务端Service的两种方式(转)

    XFire构建服务端service的两种方式,一是用xfire构建,二是和spring集成构建. 一,xifre构建,确保把xfire的jar包导入到工程中或classpath. 1,service的 ...

  2. XFire构建服务端Service的两种方式

    1.原声构建: 2.集成spring构建 http://blog.csdn.net/carefree31441/article/details/4000436XFire构建服务端Service的两种方 ...

  3. spring boot项目获取application配置文件参数的两种方式

    前言:了解过spring boot这个技术的,应该知道spring boot的核心配置文件application.properties,当然也可以通过注解自定义配置文件**.properties的信息 ...

  4. iOS开发小技巧--自定义带有占位文字的TextView(两种方式)

    自定义控件注意或框架注意:自己暴露在外面的属性,一定要重写setter,保证外界与内部的交互性 一.方案一:通过drawRect:方法将文字画到textView中,监听文字改变用的是通知中心(代理也可 ...

  5. 两种方式,花五分钟就能构建一个 Spring Boot 应用

    前言 Spring Boot 的好处自然不必多说,对于想要从事 Java 工作的朋友们来说,可谓是必学的技能. 在我看来,它的优势就是多快好省. 功能多,很多常用的能力都有集成: 接入快,简单的几行代 ...

  6. Spring Boot 定义系统启动任务,你会几种方式?

    在 Servlet/Jsp 项目中,如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web基础中的三大组件( ...

  7. Spring Boot2 系列教程(十五)定义系统启动任务的两种方式

    在 Servlet/Jsp 项目中,如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web基础中的三大组件( ...

  8. Spring集成Quartz框架的两种方式。

    可参考:https://blog.csdn.net/yk614294861/article/details/84324603 1.使用Spring与Quarta配置作业得两种方式: a.方式一,Met ...

  9. egg.js 通过 form 和 ajax 两种方式上传文件并自定义目录和文件名

    egg.js 通过 form 和 ajax 两种方式上传文件并自定义目录和文件名 评论:10 · 阅读:8437· 喜欢:0 一.需求 二.CSRF 校验 三.通过 form 表单上传文件 四.通过 ...

随机推荐

  1. JAVA编程能力提升学习图

    阿里大神毕玄整理的关于进阶JAVA的学习体系,知道下...

  2. ASP.NET Core路由中间件[1]: 终结点与URL的映射

    目录 一.路由注册 二.设置内联约束 三.默认路由参数 四.特殊的路由参数 借助路由系统提供的请求URL模式与对应终结点(Endpoint)之间的映射关系,我们可以将具有相同URL模式的请求分发给应用 ...

  3. Qt类库介绍

    QT类库 QT核心特点 QT是一个跨平台开发的类库. QT的元对象编译器MOC是一个预处理器,在源程序被编译前先将这些QT特性的程序转为标准的C++兼容的形式,然后再有标准的C++编译器进行编译.也就 ...

  4. 为什么 TCP 连接的建立需要三次握手

    TCP 的通讯双方需要发送 3 个包(即:三次握手)才能建立连接,本文将通过 3 副图来解释为什么需要 3 次握手才能建立连接. TCP 连接的建立过程本质是通信双方确认自己和对方都具有通信能力的过程 ...

  5. 如何优雅地开发HarmonyOS APP应用

    目录: 一.挖掘项目需求或者做项目移植 二.创建项目工程 三.功能模块实现的流程思路 四.养成良好的编程规范习惯以及运用设计模式 研究HarmonyOS有一段时间了,今天主要结合自己多年的项目开发经验 ...

  6. Redis Cluster 集群节点维护 (三)

    Redis Cluster 集群节点维护: 集群运行很久之后,难免由于硬件故障,网络规划,业务增长,等原因对已有集群进行相应的调整,比如增加redis nodes 节点,减少节点,节点迁移,更换服务器 ...

  7. 串口使用Pipeline时诡异的ReadOnlySequence问题

    借鉴之前的Pipeline的操作方式,现在目标是给串口读取操作也使用上Pipeline.稍微改造一下,以下代码可以直接运行. 协议为使用连续的4个0XFF作为结尾,没有头标志.数据总长为68位定长. ...

  8. 【Linux】linux中用vim来比较文件内容不同

    1. 使用vim的比较模式打开两个文件: vim -d file1 file2 或 vimdiff file1 file2 2. 如果已经打开了文件file1,再打开另一个文件file2进行比较: : ...

  9. 【Oracle】instr()函数详解

    1)instr()函数的格式  (俗称:字符查找函数) 格式一:instr( string1, string2 )    /   instr(源字符串, 目标字符串) 格式二:instr( strin ...

  10. python中IF语句容易犯的错误CASE

    python中没有switch   case类似的语句,但是下面的IF语句却与之类似,却又不同: A = B = C = D = E = 1 if A == 1: B=2 elif B ==2: C= ...