通过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 初中级程序员如何快速成长???
Java 技术学习路线 Java 语言是一门非常流行和重要的语言,目前仍是需求量很大的语言,应用范围很广的语言,在企业级开发.移动开发.大数据云计算.人工智能等领域都有大量的应用. 怎么样学习好 Ja ...
- linux resolver
linux resolver 概要 解析域名,由libresolv提供,用法参见man 3 resolver 配置文件,resolv.conf(参看 man 5 resolv.conf)配置dns s ...
- Lambda获取类属性的名字
using System; using System.ComponentModel; using System.Linq.Expressions; using System.Reflection; p ...
- Xamarin.Form 5.0: 新功能和控件以及调试改进
上周在.NET Conf 2020,Scott Hunter(.NET),Maddy Leger(微软移动开发工具-Xamarin项目经理)和David Ortinau(首席项目经理,移动开发人员工具 ...
- 讲讲Java8的Optional类
前言 Java 8中引入了 Optional 类来解决 NullPointerException 与繁琐的 null 检查,该类首次出现在 Guava.Java 8 才成为类库中的一部分. 入门 Op ...
- strings包
http://docscn.studygolang.com/pkg/strings/ Golang官方对strings包的介绍,strings包都是关于字符串的操作 常用的函数: 判断s1中是否包含字 ...
- tomcat版本号修改已dwr配置错误安全漏洞整改
1.tomcat版本信息泄露修改方法:tomcat6是在tomcat/lib 下使用jar xf catalina.jar 解压这个jar包会得到两个目录:META-INF和org其中org\apac ...
- 如何写一个自己的组件库,打成NPM包,并上传到NPM远程
1.首先使用vue create my_project 构建一个自己的Vue项目 2.vue.config.js和package.json配置如下,做了些修改 const path = require ...
- SQL LEN()函数用法
含义: LEN 函数返回文本字段中值的长度. 返回字符表达式中的字符数 SQL LEN() 语法 SELECT LEN(column_name) FROM table_name 举例: 1.LEN对相 ...
- dig的安装和使用
-bash: dig: command not found 解决办法: yum -y install bind-utils dig www.baid bu.com 查看a记录 dig www.ba ...