通过spring statemmachine 自定义构建属于自己的状态机(两种方式)
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 自定义构建属于自己的状态机(两种方式)的更多相关文章
- XFire构建服务端Service的两种方式(转)
XFire构建服务端service的两种方式,一是用xfire构建,二是和spring集成构建. 一,xifre构建,确保把xfire的jar包导入到工程中或classpath. 1,service的 ...
- XFire构建服务端Service的两种方式
1.原声构建: 2.集成spring构建 http://blog.csdn.net/carefree31441/article/details/4000436XFire构建服务端Service的两种方 ...
- spring boot项目获取application配置文件参数的两种方式
前言:了解过spring boot这个技术的,应该知道spring boot的核心配置文件application.properties,当然也可以通过注解自定义配置文件**.properties的信息 ...
- iOS开发小技巧--自定义带有占位文字的TextView(两种方式)
自定义控件注意或框架注意:自己暴露在外面的属性,一定要重写setter,保证外界与内部的交互性 一.方案一:通过drawRect:方法将文字画到textView中,监听文字改变用的是通知中心(代理也可 ...
- 两种方式,花五分钟就能构建一个 Spring Boot 应用
前言 Spring Boot 的好处自然不必多说,对于想要从事 Java 工作的朋友们来说,可谓是必学的技能. 在我看来,它的优势就是多快好省. 功能多,很多常用的能力都有集成: 接入快,简单的几行代 ...
- Spring Boot 定义系统启动任务,你会几种方式?
在 Servlet/Jsp 项目中,如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web基础中的三大组件( ...
- Spring Boot2 系列教程(十五)定义系统启动任务的两种方式
在 Servlet/Jsp 项目中,如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web基础中的三大组件( ...
- Spring集成Quartz框架的两种方式。
可参考:https://blog.csdn.net/yk614294861/article/details/84324603 1.使用Spring与Quarta配置作业得两种方式: a.方式一,Met ...
- egg.js 通过 form 和 ajax 两种方式上传文件并自定义目录和文件名
egg.js 通过 form 和 ajax 两种方式上传文件并自定义目录和文件名 评论:10 · 阅读:8437· 喜欢:0 一.需求 二.CSRF 校验 三.通过 form 表单上传文件 四.通过 ...
随机推荐
- java.util.Collections
p.p1 { margin: 0; font: 11px Monaco } span.s1 { text-decoration: underline } span.s2 { color: rgba(1 ...
- CentOS 7 最小化安装及优化
CentOS 7 最小化安装及优化 目录 CentOS 7 最小化安装及优化 一.下载镜像文件 官方网站 国内镜像源 一.VMware 配置虚拟网络 二.VMware 新建虚拟机 三.CentOS 7 ...
- 原来大数据 Hadoop 是这样存储数据的
HDFS概述 产生背景 随着数据量越来越大,在一个操作系统中存不下所有的数据.需要将这些数据分配到更多的操作系统中,带来的问题是多操作系统不方便管理和维护.需要一种系统来管理多台机器上的文件,这就是分 ...
- 利用python 5分钟制作一款小游戏
1.安装pygame 在命令行cmd中输入:pip install pygame ( 注:如果安装不成功,需要输入:python -m pip install --user --upgrade pip ...
- WPF学习笔记02_布局
布局原则 WPF窗口只能包含单个元素.如果要放置多个元素,需要放置一个容器,然后在容器中添加元素. 不应显示的设定元素的尺寸 不应该使用屏幕坐标指定元素的位置 布局容器的子元素"共享&quo ...
- Eslint提示const关键字被保留
如果在使用eslint的时候提示: error Parsing error: The keyword 'const' is reserved 有可能是因为eslint默认审查的es5,需要明确让他审查 ...
- 【剑指 Offer】03.数组中重复的数字
题目描述 找出数组中重复的数字. 在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次.请找出数组中 ...
- 剑指offer 面试题4:二维数组中的查找
题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...
- 【Linux】reverse mapping checking getaddrinfo for XXX.XXXX.com failed - POSSIBLE BREAKIN ATTEMPT!
------------------------------------------------------------------------------------------------- | ...
- java 文件上传的那些事
文件上传 逻辑 @Value("${sava_path}") private String sava_path; @Override public String saveFile( ...