- 主页 > 生活百科 > >
Spring Statemachine应用实践( 三 )
StateMachineService 这个类是spring statemachine自带的接口,用于获取和释放一个状态机的辅助service,依赖状态机工厂和持久化 实例,但由于默认实现 StateMachinePersist< S, E, String> 规定了StateMachineContext的泛型为String 类型,故而持久层的参数contextObj 为string 类型,实际是状态机的id 。 持久化 spring-statemachine官方支持MongoDB和redis持久化存储,开发无需关心状态持久化,但是存在业务数据存储和状态存储事务的问题,这里需要自己实现(StateMachineRuntimePersister)持久化以存储状态 。 上下文传递时都使用的StateMachineContext,其内部包含StateMachine实例,可以通过增加StateMachine实例扩展参数传递参数 。Guard与Action
@Componentpublic class SaveGuard implements Guard<State, Event> {@Overridepublic boolean evaluate(StateContext<State, Event> context) {log.info("[execute save guard]");return true;}}@Componentpublic class SaveAction implements Action<State, Event> {@Overridepublic void execute(StateContext<State, Event> context) {try {log.info("[execute saveAction]");} catch (Exception e) {context.getExtendedState().getVariables().put("ERROR", e.getMessage());}}}说明:
- Guard 门卫,条件判断返回true时再执行状态转移,可以做业务前置校验 。
持久化配置
@Componentpublic class ActivityStateMachinePersister extends AbstractStateMachineRuntimePersister<State, Event, String> {@Autowiredprivate ActivityStateService activityStateService;@Overridepublic void write(StateMachineContext<State, Event> context, String id) {Activity state = new Activity();state.setMachineId(id);state.setState(context.getState());activityStateService.save(state);}@Overridepublic StateMachineContext<State, Event> read(String id) {return deserialize(activityStateService.getContextById(id));}}说明:
- AbstractStateMachineRuntimePersister 继承AbstractPersistingStateMachineInterceptor 并实现了StateMachineRuntimePersister接口,AbstractPersistingStateMachineInterceptor主要拦截状态变更时的状态监听 。不同于StateMachineListener被动监听,interceptor拥有可以改变状态变化链的能力 。
- 序列化存储实现参考了spring-statemachine-data-redis的实现 。
状态服务调用
@Servicepublic class StateTransitService {@Autowiredprivate StateMachineService<State, Event> stateMachineService;@Transactionalpublic void transimit(String machineId, Message<Event> message) {StateMachine<State, Event> stateMachine = stateMachineService.acquireStateMachine(machineId);stateMachine.addStateListener(new DefaultStateMachineListener<>(stateMachine));stateMachine.sendEvent(message);if (stateMachine.hasStateMachineError()) {String errorMessage = stateMachine.getExtendedState().get("message", String.class);stateMachineService.releaseStateMachine(machineId);throw new ResponseException(errorMessage);}}}@AllArgsConstructorpublic class DefaultStateMachineListener<S, E> extends StateMachineListenerAdapter<S, E> {private final StateMachine<S, E> stateMachine;@Overridepublic void eventNotAccepted(Message<E> event) {stateMachine.getExtendedState().getVariables().put("message", "当前状态不满足执行条件");stateMachine.setStateMachineError(new ResponseException(500, "Event not accepted"));}@Overridepublic void transitionEnded(Transition<S, E> transition) {log.info("source {} to {}", transition.getSource().getId(), transition.getTarget().getId());}}说明:
- Message为发送事件的载体,其内部封装了消息体、事件等上下文扩展参数 。
- StateMachineListenerAdapter为默认监听接口的空实现,依据业务需要重写监听的方法 。
- eventNotAccepted此为事件未正确执行时的监听器 。
集成单元测试
@SpringBootTest@RunWith(SpringRunner.class)public class StateMachineITest {@Autowiredprivate StateTransitService transmitService;@Autowiredprivate ActivityStateService activityStateService;@Testpublic void test() {String machineId = "test";//业务主键IDtransmitService.transimit(machineId, MessageBuilder.withPayload(Event.SAVE).build());transmitService.transimit(machineId, MessageBuilder.withPayload(Event.SUBMIT).build());transmitService.transimit(machineId, MessageBuilder.withPayload(Event.PASS).build());transmitService.transimit(machineId, MessageBuilder.withPayload(Event.ONLINE).build());transmitService.transimit(machineId, MessageBuilder.withPayload(Event.ONLINE).build());transmitService.transimit(machineId, MessageBuilder.withPayload(Event.OFFLINE).build());assert activityStateService.getStateById(machineId).equals(State.FINISHED);}}
推荐阅读
-
姿态时尚|戴安娜姐姐碎花裙搭衬衫绝了,曾俘获查尔斯,却因穿得太高调被甩
-
「娱乐大家说说」它2.0T+279匹马力,百公里仅需6.2秒!,中型车不一定非要选雅阁
-
-
汽车小哥哥|看了她妹妹的素颜,到底谁才是女爱豆?,以为杨超越够美了
-
苹果手机如何刷机还原,iphone不用电脑刷机教程
-
全国首个认知功能筛查公益活动启动 连锁药店配专业人士和测量表
-
[]五一小长假怎么安排?自驾游游客将超七成,健康游成为关注热点
-
杨幂|《狐妖小红娘》系列女主对比,85花难敌95花,杨幂得靠龚俊逆转
-
坤坤说历史|你曾经是个王者,直到你妈妈来了!,搞笑GIF趣图:哥们
-
【梓盺】,誓死捍卫冠军荣耀,LPL最有希望的一年,五只银河战舰即将起航
-
家乡体育|曝北京重签4冠王高帅富,NBA总冠军林书豪无缘回归?,大反转
-
小懒猫|朱祁镇复位太容易,为何朱祁钰和于谦未能阻,被囚7年突然爆发
-
张豆豆|体操女神张豆豆因挺胸照走红!秀高难度一字马,不进娱乐圈考北体
-
吉尼斯世界纪录|破吉尼斯世界纪录,英国一男子用头顶起46卷厕纸
-
【软件】荣耀30Pro+深度体验一周:不吹不黑,感觉像小P40Pro
-
新华网客户端|| 虎嗅调研Vol.7,疫情“被迫”买车,首选不是电动车
-
-
「ROM乐园TB」小米红米手机新机9008模式怎么进入?小米线刷救砖模式
-
double是什么意思(double男是什么意思)
-
空姐|马斯克被空姐指控性骚扰 本人再回应:完全不真实、有本事说出我胎记