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. 对于home主页的切换处理

    经过测试,发现,在home首页的时候,滑动到某一个位置的时候,如果再点击tabbar中的"购物车"."分类"或者"我的"的时候,再点击到首页 ...

  2. ES6模板字符串及字符串的扩展方法

    一.ES6模板字符串 传统定义字符串的方式是: const str='hello es2015,this is a string' ES6新增了一种定义字符串的方式用反引号进行标识 const str ...

  3. i5 11300H 怎么样 相当于什么水平

    i5-11300H 为 4 核 8 线程,主频 3.1GHz,睿频 4.4GHz,三级缓存 8MBi5-11300H 怎么样看完你就知道了 https://list.jd.com/list.html?

  4. springboot项目打war包流程

    目前,前后端分离的架构已成主流,因此使用springboot构建应用是非常快速的,项目发布到服务器上的时候,只需要打成一个jar包,然后通过命令 : java -jar jar包名称即可启动服务了:但 ...

  5. OpenTelemetry - 云原生下可观测性的新标准

    CNCF 简介 CNCF(Cloud Native Computing Foundation),中文为"云原生计算基金会",CNCF是Linux基金会旗下的基金会,可以理解为一个非 ...

  6. 【SpringBoot1.x】SpringBoot1.x 开发热部署和监控管理

    SpringBoot1.x 开发热部署和监控管理 热部署 在开发中我们修改一个 Java 文件后想看到效果不得不重启应用,这导致大量时间花费,我们希望不重启应用的情况下,程序可以自动部署(热部署). ...

  7. 【剑指 Offer】10-I.斐波那契数列

    题目描述 写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项.斐波那契数列的定义如下: F(0) = 0,   F(1) = 1 F(N) = F(N - 1) + F(N - ...

  8. LeetCode662 二叉树最大宽度

    给定一个二叉树,编写一个函数来获取这个树的最大宽度.树的宽度是所有层中的最大宽度.这个二叉树与满二叉树(full binary tree)结构相同,但一些节点为空. 每一层的宽度被定义为两个端点(该层 ...

  9. 通过show status 命令了解各种sql的执行频率

    show status like 'Com_%'; Com_select                | 1   执行select操作的次数,一次查询只累加1 Com_insert         ...

  10. 【Linux】centos 7中,开机不执行rc.lcoal中的命令

    最近将一些需要开机启动的命令添加到了rc.local中 本想着开机就启动了,很省事 但是一次意外的重启,发现rc.local中的全部命令都没有执行 发现问题后,及时查找 参考:https://blog ...