1.背景
1.1 spring statemachine是干啥用的
有限状态机(英语:finite-state machine,缩写:FSM),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。将状态和事件控制从不同的业务Service方法的if else中抽离出来。FSM的应用范围很广,对于有复杂状态流,扩展性要求比较高的场景都可以使用该模型。下面是状态机模型中的4个要素,即现态、条件、动作、次态。
现态:是指当前所处的状态。
条件:又称为“事件”。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。
状态机对于流程性、状态变化的场景,它就是一个清晰的表达方式,这就是它的好处。
2.入门案例
使用maven项目,首先引入包
pom.xml
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.statemachine</groupId> <artifactId>spring-statemachine-core</artifactId> <version>1.2.0.RELEASE</version> </dependency> </dependencies>
讯享网
配置文件
StateMachineConfig.java
讯享网package com.huaquan.securityguard.config; import com.huaquan.securityguard.enums.EventEnum; import com.huaquan.securityguard.enums.StatusEnum; import org.springframework.context.annotation.Configuration; import org.springframework.statemachine.config.EnableStateMachine; import org.springframework.statemachine.config.EnableStateMachineFactory; import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter; import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; import java.util.EnumSet; / * @author 陆杰 * @since 0.1 */ @Configuration @EnableStateMachine public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<StatusEnum, EventEnum> { / * 初始化状态机状态 */ @Override public void configure(StateMachineStateConfigurer<StatusEnum, EventEnum> states) throws Exception { states.withStates() // 定义初始状态 .initial(StatusEnum.UNCONNECTED) // 定义状态机状态 .states(EnumSet.allOf(StatusEnum.class)); } / * 初始化状态迁移事件 */ @Override public void configure(StateMachineTransitionConfigurer<StatusEnum, EventEnum> transitions) throws Exception { transitions // 1.连接事件 // 未连接 -> 已连接 .withExternal() .source(StatusEnum.UNCONNECTED) .target(StatusEnum.START) .event(EventEnum.CONNECT) .and() // 2.更新事件 // 已连接 -> 更新中 .withExternal() .source(StatusEnum.START) .target(StatusEnum.UPDATE) .event(EventEnum.UPDATE) .and() // 更新过期人员 .withExternal() .source(StatusEnum.START) .target(StatusEnum.UPDATE_EXPER) .event(EventEnum.UPDATE_EXPER) .and() .withExternal() .source(StatusEnum.UPDATE_EXPER) .target(StatusEnum.END) .event(EventEnum.UPDATE_SUCCESS) .and() // 3.更新成功事件 //更新中 -> 已完成 .withExternal() .source(StatusEnum.UPDATE) .target(StatusEnum.END) .event(EventEnum.UPDATE_SUCCESS) .and() // 5.结束事件 // 已完成 -> 未连接 .withExternal() .source(StatusEnum.END) .target(StatusEnum.UNCONNECTED) .event(EventEnum.END) ; } }
StateMachineEventConfig.java
package com.huaquan.securityguard.config; import com.huaquan.securityguard.service.ISqliteService; import com.huaquan.securityguard.service.impl.InfoService; import com.huaquan.securityguard.util.IApiUtil; import com.huaquan.securityguard.util.ISeverUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.statemachine.annotation.OnTransition; import org.springframework.statemachine.annotation.WithStateMachine; / * 功能:状态机 * 2019年6月22日 v0.1 * * @author 陆杰 * @since 0.1 */ @WithStateMachine public class StateMachineEventConfig { Logger logger = LoggerFactory.getLogger(InfoService.class); @Autowired private ISqliteService iSqliteService; @Autowired private InfoService infoService; @Autowired private ISeverUtil iSeverUtil; @Autowired private IApiUtil iApiUtil; @OnTransition(source = "UNCONNECTED", target = "START") public void connect() { iApiUtil.login(); logger.info("连接事件, 未连接 -> 已连接"); } @OnTransition(source = "START", target = "UPDATE") public void update() throws InterruptedException { logger.info("UpdateIncrease----"); // iSqliteService.insertLogViewWithStartTime(iSeverUtil.timeLtoS(System.currentTimeMillis())); infoService.UpdateTheFailMessage(); infoService.UpdateFromRemoteDB(); Thread.sleep(2000); } @OnTransition(source = "START", target = "UPDATE_EXPER") public void upExperson() throws InterruptedException { logger.info("UpdateEx----"); infoService.UpdateExPerson(); Thread.sleep(2000); } @OnTransition(source = "UPDATE", target = "END") public void updateSuccess() { logger.info("update success!"); } @OnTransition(source = "END", target = "UNCONNECTED") public void unConnectSuccess() { logger.info("connect cancel"); } }
enums 枚举,状态机中表示状态
EventEnum.java
讯享网public enum EventEnum { //未连接 UNCONNECTED, // 连接 CONNECT, // 更新 UPDATE, // 更新成功 UPDATE_SUCCESS, // 更新过期人员 UPDATE_EXPER, // 更新失败 UPDATE_FAILED, // 注销 END; }
StatusEnum.java
public enum StatusEnum { // 未连接 UNCONNECTED, //开始 START, // 更新中 UPDATE, // 更新过期人员 UPDATE_EXPER, // 结束 END, }
启动状态机
讯享网@Autowired private StateMachine<StatusEnum, EventEnum> stateMachine;//引入状态机 stateMachine.start(); stateMachine.sendEvent(EventEnum.CONNECT); stateMachine.sendEvent(EventEnum.UPDATE); stateMachine.sendEvent(EventEnum.UPDATE_SUCCESS); stateMachine.sendEvent(EventEnum.END); stateMachine.sendEvent(EventEnum.UNCONNECTED);
(1)在实际使用中,应该是有很多任务的流程在同时跑,而不是像这个例子,全部任务共用一个流程,一个订单到EventEnum.UNCONNECTED状态了,其他任务就不能是UPDATE状态了。
(2)参数问题,我们做项目,不是为了看日志打出“---订单创建,待支付---”给我们玩的,而是要处理具体业务的,拿订单流程来说吧,订单号怎么传,状态改变时间怎么回数据库,等等问题其实都需要解决。
(3)存储问题,状态机如果有多个,需要的时候从哪去,暂时不需要了放哪去,这都是问题,所以存储状态机也是需要解决的。
3.多个状态机共存

在实际项目中一般性都会有多个状态机并发执行,在上面的例子中在程序中同时执行只能同时存在一个状态机,如果想要多个状态机并发就需要用到builer
StateMachineBuilder.Builder<OrderStates, OrderEvents> builder = StateMachineBuilder.builder();
OrderStateMachineBuilder.java
讯享网private final static String MACHINEID = "orderMachine"; public StateMachine<OrderStates, OrderEvents> build(BeanFactory beanFactory) throws Exception { StateMachineBuilder.Builder<OrderStates, OrderEvents> builder = StateMachineBuilder.builder(); System.out.println("构建订单状态机"); builder.configureConfiguration() .withConfiguration() .machineId(MACHINEID) .beanFactory(beanFactory); builder.configureStates() .withStates() .initial(OrderStates.UNPAID) .states(EnumSet.allOf(OrderStates.class)); builder.configureTransitions() .withExternal() .source(OrderStates.UNPAID).target(OrderStates.WAITING_FOR_RECEIVE) .event(OrderEvents.PAY).action(action()) .and() .withExternal() .source(OrderStates.WAITING_FOR_RECEIVE).target(OrderStates.DONE) .event(OrderEvents.RECEIVE); return builder.build(); }
其中MACHINEID指向EventConfig
private final static String MACHINEID = "orderMachine";
讯享网 builder.configureConfiguration() .withConfiguration() .machineId(MACHINEID) .beanFactory(beanFactory);
当然为了能调用到EventConfig,需要在EventConfig中注明它的名字,在1.x版本中不存在id这个字段,所以是无法关联的
@WithStateMachine(id="orderMachine")
在WithStateMachine中有两个字段
讯享网public @interface WithStateMachine { String name() default "stateMachine"; String id() default ""; }
OrderEventConfig.java
@WithStateMachine(id="orderMachine") public class OrderEventConfig { private Logger logger = LoggerFactory.getLogger(getClass()); / * 当前状态UNPAID */ @OnTransition(target = "UNPAID") public void create() { logger.info("---订单创建,待支付---"); } / * UNPAID->WAITING_FOR_RECEIVE 执行的动作 */ @OnTransition(source = "UNPAID", target = "WAITING_FOR_RECEIVE") public void pay(Message<OrderEvents> message) { System.out.println("传递的参数:" + message.getHeaders().get("order")); logger.info("---用户完成支付,待收货---"); } / * WAITING_FOR_RECEIVE->DONE 执行的动作 */ @OnTransition(source = "WAITING_FOR_RECEIVE", target = "DONE") public void receive(Message<OrderEvents> message) { System.out.println("传递的参数:" + message.getHeaders().get("order")); System.out.println("传递的参数:" + message.getHeaders().get("otherObj")); logger.info("---用户已收货,订单完成---"); } }
调用状态机代码,在调用状态机时候,现在每一次调用都会新建一个状态机并发运行。

讯享网StateMachine<OrderStates, OrderEvents> stateMachine = orderStateMachineBuilder.build(beanFactory); System.out.println(stateMachine.getId()); // 创建流程 stateMachine.start(); // 触发PAY事件 stateMachine.sendEvent(OrderEvents.PAY); // 触发RECEIVE事件 //stateMachine.sendEvent(OrderEvents.RECEIVE); //用message传递数据 Order order = new Order(orderId, String.valueOf(Math.random()), "华师大科技园", "", "RECEIVE"); Message<OrderEvents> message = MessageBuilder.withPayload(OrderEvents.RECEIVE).setHeader("order", order).setHeader("otherObj", "otherObjValue").build(); stateMachine.sendEvent(message); // 获取最终状态 System.out.println("最终状态:" + stateMachine.getState().getId());
调用结果,因为这里的状态不是一个循环,如果不是并发创建新的状态机是无法第二次执行打印状态机执行的内容的。
2020-05-13 10:50:04.645 INFO 12176 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$928f5e35 : ---用户完成支付,待收货--- 传递的参数:Order [id=null, userId=0.53066, address=华师大科技园, phoneNum=, state=RECEIVE] 传递的参数:otherObjValue 2020-05-13 10:50:04.648 INFO 12176 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$928f5e35 : ---用户已收货,订单完成--- 最终状态:DONE 构建订单状态机 orderMachine 2020-05-13 10:50:09.395 INFO 12176 --- [nio-9991-exec-2] tConfig$$EnhancerBySpringCGLIB$$928f5e35 : ---订单创建,待支付--- 2020-05-13 10:50:09.396 INFO 12176 --- [nio-9991-exec-2] o.s.s.support.LifecycleObjectSupport : started org.springframework.statemachine.support.DefaultStateMachineExecutor@cf 2020-05-13 10:50:09.396 INFO 12176 --- [nio-9991-exec-2] o.s.s.support.LifecycleObjectSupport : started DONE UNPAID WAITING_FOR_RECEIVE / UNPAID / uuid=e9b620a5-cfe1-4018-b0d0-f5c14046f760 / id=orderMachine DefaultStateContext [stage=TRANSITION, message=GenericMessage [payload=PAY, headers={id=36d3ed81-88ce-8524-db84-a791a258b891, timestamp=96}], messageHeaders={id=5cb640ed-3d05-972e-a291-eb2a66377b66, _sm_id_=e9b620a5-cfe1-4018-b0d0-f5c14046f760, timestamp=96}, extendedState=DefaultExtendedState [variables={}], transition=AbstractTransition [source=ObjectState [getIds()=[UNPAID], getClass()=class org.springframework.statemachine.state.ObjectState, hashCode()=, toString()=AbstractState [id=UNPAID, pseudoState=org.springframework.statemachine.state.DefaultPseudoState@1546ee, deferred=[], entryActions=[], exitActions=[], stateActions=[], regions=[], submachine=null]], target=ObjectState [getIds()=[WAITING_FOR_RECEIVE], getClass()=class org.springframework.statemachine.state.ObjectState, hashCode()=, toString()=AbstractState [id=WAITING_FOR_RECEIVE, pseudoState=null, deferred=[], entryActions=[], exitActions=[], stateActions=[], regions=[], submachine=null]], kind=EXTERNAL, guard=null], stateMachine=DONE UNPAID WAITING_FOR_RECEIVE / UNPAID / uuid=e9b620a5-cfe1-4018-b0d0-f5c14046f760 / id=orderMachine, source=null, target=null, sources=null, targets=null, exception=null] 传递的参数:null 2020-05-13 10:50:09.397 INFO 12176 --- [nio-9991-exec-2] tConfig$$EnhancerBySpringCGLIB$$928f5e35 : ---用户完成支付,待收货--- 传递的参数:Order [id=null, userId=0.86407, address=华师大科技园, phoneNum=, state=RECEIVE] 传递的参数:otherObjValue 2020-05-13 10:50:09.397 INFO 12176 --- [nio-9991-exec-2] tConfig$$EnhancerBySpringCGLIB$$928f5e35 : ---用户已收货,订单完成--- 最终状态:DONE
4.多种状态机共存
在实际需求中,一个程序可能有不同种类的状态机,服务不同的需求所以往往需要多个状态机,在实际操作中,我们只需要把创建状态机的步骤再做一遍取不同的名字就可以在一个程序内创建不同的状态机了。



在builder中根据需求各自创建config
讯享网private final static String MACHINEID = "orderMachine"; public StateMachine<OrderStates, OrderEvents> build(BeanFactory beanFactory) throws Exception { StateMachineBuilder.Builder<OrderStates, OrderEvents> builder = StateMachineBuilder.builder(); System.out.println("构建订单状态机"); builder.configureConfiguration() .withConfiguration() .machineId(MACHINEID) .beanFactory(beanFactory); ...省略 private final static String MACHINEID = "formMachine"; public StateMachine<FormStates, FormEvents> build(BeanFactory beanFactory) throws Exception { StateMachineBuilder.Builder<FormStates, FormEvents> builder = StateMachineBuilder.builder(); System.out.println("构建表单状态机"); builder.configureConfiguration() .withConfiguration() .machineId(MACHINEID) .beanFactory(beanFactory); ...省略
各自声明对应的eventConfig
@WithStateMachine(id="orderMachine") public class OrderEventConfig { ...省略 @WithStateMachine(id="formMachine") public class FormEventConfig {
分别执行不同的状态机
讯享网@RequestMapping("/testOrderState") public void testOrderState(String orderId) throws Exception { StateMachine<OrderStates, OrderEvents> stateMachine = orderStateMachineBuilder.build(beanFactory); System.out.println(stateMachine.getId()); // 创建流程 stateMachine.start(); // 触发PAY事件 stateMachine.sendEvent(OrderEvents.PAY); // 触发RECEIVE事件 stateMachine.sendEvent(OrderEvents.RECEIVE); // 获取最终状态 System.out.println("最终状态:" + stateMachine.getState().getId()); } @RequestMapping("/testFormState") public void testFormState() throws Exception { StateMachine<FormStates, FormEvents> stateMachine = formStateMachineBuilder.build(beanFactory); System.out.println(stateMachine.getId()); // 创建流程 stateMachine.start(); stateMachine.sendEvent(FormEvents.WRITE); stateMachine.sendEvent(FormEvents.CONFIRM); stateMachine.sendEvent(FormEvents.SUBMIT); // 获取最终状态 System.out.println("最终状态:" + stateMachine.getState().getId()); }
5.传递参数的Message
在企业开发中,数据在不同的业务间传输是最常见的工作,所以虽然我们的主架构是用的状态机,也就是从流程状态的角度来看待这个项目,但在具体业务中,每个状态的转变中会牵涉到各类业务,这些业务有些需要收到状态机变化的通知,需要把状态值传递给业务类和业务方法,同样的,在处理状态变化是,也需要获取业务数据,方便不同的业务在同一个状态变化环节做各自的业务,下面我们就讲下这个数据在spring statemachine里面的传递。
通过message传递,message只有两部分,header和payload
public interface Message<T> { T getPayload(); MessageHeaders getHeaders(); }
传参数,在调用状态机时候,在message中可以传递对象,或者基础数据类型,在payload中装载状态即可
讯享网Message<OrderEvents> message = MessageBuilder.withPayload(OrderEvents.PAY).setHeader("order", order).setHeader("otherObj", "otherObjValue").build(); stateMachine.sendEvent(message);
与普通不装消息的设置状态对比
stateMachine.sendEvent(OrderEvents.PAY);
在接收端,即EventConfig中,方法中添加参数Message<OrderEvents> message,用于获取发过来的message
讯享网@OnTransition(source = "WAITING_FOR_RECEIVE", target = "DONE") public void receive(Message<OrderEvents> message) { System.out.println("传递的参数:" + message.getHeaders().get("order")); System.out.println("传递的参数:" + message.getHeaders().get("otherObj")); logger.info("---用户已收货,订单完成---"); }
6.Statemachine持久化

持久化操作在实际业务中经常遇到,有时候需要对一个任务隔天处理,或者再久一点等到需要的时候再拿出来,这时候就要用到持久化操作。
6.1持久化在本地内存中(Map保存)
用唯一id作为key,把状态机保存到map表里面,在实际的业务中,自由存取
public class MachineMap { public static Map<String,StateMachine<OrderStates, OrderEvents>> orderMap = new HashMap<String,StateMachine<OrderStates, OrderEvents>>(); public static Map<String,StateMachine<FormStates, FormEvents>> formMap = new HashMap<String,StateMachine<FormStates, FormEvents>>(); }
关于StateMachinePersist和StateMachinePersister接口:
这两个接口名字很类似,很容易搞混,但下面的是有er的,包名也不同的。StateMachinePersister是可以直接保存StateMachine对象的,对于StateMachinePersist首先要实现它,然后再一个Config类里面转换成下面的StateMachinePersister,转换的代码就在上面的PersistConfig类里。
StateMachinePersist.class和StateMachinePersister.class对比
讯享网package org.springframework.statemachine; public interface StateMachinePersist<S, E, T> { void write(StateMachineContext<S, E> context, T contextObj) throws Exception; StateMachineContext<S, E> read(T contextObj) throws Exception; } package org.springframework.statemachine.persist; import org.springframework.statemachine.StateMachine; public interface StateMachinePersister<S, E, T> { void persist(StateMachine<S, E> stateMachine, T contextObj) throws Exception; StateMachine<S, E> restore(StateMachine<S, E> stateMachine, T contextObj) throws Exception; }
上述描述如何使用StateMachinePersist可能有点模糊,以下为具体步骤:
Step1:StateMachinePersist
@Component public class InMemoryStateMachinePersist implements StateMachinePersist<OrderStates, OrderEvents, String> { private Map<String, StateMachineContext<OrderStates, OrderEvents>> map = new HashMap<String, StateMachineContext<OrderStates,OrderEvents>>(); @Override public void write(StateMachineContext<OrderStates, OrderEvents> context, String contextObj) throws Exception { map.put(contextObj, context); } @Override public StateMachineContext<OrderStates, OrderEvents> read(String contextObj) throws Exception { return map.get(contextObj); } }
Step2:然后在 PersistConfig 中 注入:InMemoryStateMachinePersist
讯享网@Configuration public class PersistConfig { @Autowired private InMemoryStateMachinePersist inMemoryStateMachinePersist; / * 注入StateMachinePersister对象 * * @return */ @Bean(name="orderMemoryPersister") public StateMachinePersister<OrderStates, OrderEvents, String> getPersister() { return new DefaultStateMachinePersister<>(inMemoryStateMachinePersist); } }
Step3: 调用时根据bean注入
@Resource(name="orderMemoryPersister") private StateMachinePersister<OrderStates, OrderEvents, String> orderMemorypersister; ... StateMachine<OrderStates, OrderEvents> stateMachine = orderStateMachineBuilder.build(beanFactory); stateMachine.start(); //发送PAY事件 stateMachine.sendEvent(OrderEvents.PAY); Order order = new Order(); order.setId(id); //持久化stateMachine orderMemorypersister.persist(stateMachine, order.getId()); ... //取数据 StateMachine<OrderStates, OrderEvents> stateMachine = orderStateMachineBuilder.build(beanFactory); orderMemorypersister.restore(stateMachine, id); System.out.println("恢复状态机后的状态为:" + stateMachine.getState().getId());
6.2持久化到redis
pom.xml 依赖
讯享网<!-- redis持久化状态机 --> <dependency> <groupId>org.springframework.statemachine</groupId> <artifactId>spring-statemachine-redis</artifactId> <version>1.2.9.RELEASE</version> </dependency>
redis配置
# REDIS (RedisProperties) # Redis数据库索引(默认为0) spring.redis.database=0 # Redis服务器地址 spring.redis.host=localhost # Redis服务器连接端口 spring.redis.port=6379 # Redis服务器连接密码(默认为空) spring.redis.password= # 连接池最大连接数(使用负值表示没有限制) spring.redis.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.pool.max-wait=-1 # 连接池中的最大空闲连接 spring.redis.pool.max-idle=8 # 连接池中的最小空闲连接 spring.redis.pool.min-idle=0 # 连接超时时间(毫秒) spring.redis.timeout=0
跟上面map存储一样,在配置文件内配置redis信息
PersistConfig.java
讯享网@Autowired private RedisConnectionFactory redisConnectionFactory; ... / * 注入RedisStateMachinePersister对象 * * @return */ @Bean(name = "orderRedisPersister") public RedisStateMachinePersister<OrderStates, OrderEvents> redisPersister() { return new RedisStateMachinePersister<>(redisPersist()); } / * 通过redisConnectionFactory创建StateMachinePersist * * @return */ public StateMachinePersist<OrderStates, OrderEvents,String> redisPersist() { RedisStateMachineContextRepository<OrderStates, OrderEvents> repository = new RedisStateMachineContextRepository<>(redisConnectionFactory); return new RepositoryStateMachinePersist<>(repository); }
调用
@RequestMapping("/testRedisPersister") public void testRedisPersister(String id) throws Exception { StateMachine<OrderStates, OrderEvents> stateMachine = orderStateMachineBuilder.build(beanFactory); stateMachine.start(); Order order = new Order(); order.setId(id); //发送PAY事件 Message<OrderEvents> message = MessageBuilder.withPayload(OrderEvents.PAY).setHeader("order", order).build(); stateMachine.sendEvent(message); //持久化stateMachine orderRedisPersister.persist(stateMachine, order.getId()); } @RequestMapping("/testRedisPersisterRestore") public void testRestore(String id) throws Exception { StateMachine<OrderStates, OrderEvents> stateMachine = orderStateMachineBuilder.build(beanFactory); orderRedisPersister.restore(stateMachine, id); System.out.println("恢复状态机后的状态为:" + stateMachine.getState().getId()); }
7.statement伪持久化和中间段状态机

在实际的企业开发中,不可能所有情况都是从头到尾的按状态流程来,会有很多意外,比如历史数据,故障重启后的遗留流程......,所以这种可以任意调节状态的才是我们需要的状态机。
简而言之就是直接拿到状态机的一个中间过成,并可以继续执行。
回到persisit的实现类,既然目的是为了拿到一个中间段的状态机,那么就没有必要存当前状态了
讯享网@Component public class OrderStateMachinePersist implements StateMachinePersist<OrderStates, OrderEvents, Order> { @Override public void write(StateMachineContext<OrderStates, OrderEvents> context, Order contextObj) throws Exception { //这里不做任何持久化工作 } @Override public StateMachineContext<OrderStates, OrderEvents> read(Order contextObj) throws Exception { StateMachineContext<OrderStates, OrderEvents> result = new DefaultStateMachineContext<OrderStates, OrderEvents>(OrderStates.valueOf(contextObj.getState()), null, null, null, null, "orderMachine"); return result; } }
跟之前的步骤一样把persist注入到config文件中
@Configuration public class PersistConfig { @Autowired private OrderStateMachinePersist orderStateMachinePersist; @Bean(name="orderPersister") public StateMachinePersister<OrderStates, OrderEvents, Order> orderPersister() { return new DefaultStateMachinePersister<OrderStates, OrderEvents, Order>(orderStateMachinePersist); } }
在执行的地方用通过persisiter拿到操作类
讯享网@RestController @RequestMapping("/statemachine") public class StateMachineController { @Resource(name="orderPersister") private StateMachinePersister<OrderStates, OrderEvents, Order> persister; @RequestMapping("/testOrderRestore") public void testOrderRestore(String id) throws Exception { StateMachine<OrderStates, OrderEvents> stateMachine = orderStateMachineBuilder.build(beanFactory); //订单 Order order = new Order(); order.setId(id); order.setState(OrderStates.WAITING_FOR_RECEIVE.toString()); //恢复 persister.restore(stateMachine, order); System.out.println("恢复后的状态:" + stateMachine.getState().getId()); stateMachine.sendEvent(OrderEvents.RECEIVE); //查看恢复后状态机的状态 System.out.println("执行下一步后的状态:" + stateMachine.getState().getId()); } }
构建订单状态机 恢复后的状态:WAITING_FOR_RECEIVE 传递的参数:null 传递的参数:null 执行下一步后的状态:DONE

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/51871.html