假设我们有以下状态机配置:
transitions.withExternal()
.source(FIRST)
.target(SECOND)
.event(STEP_EVENT)
.and()
.source(SECOND)
.target(EXIT)
.event(EXIT_EVENT)
事件列表:STEP_EVENT、EXIT_EVENT、UNUSED_EVENT
stateMachine.init();
// FIRST state
stateMachine.sendEvent(STEP_EVENT);
/* state moves to SECOND
because there is a transition with current state as a source
and STEP_EVENT as transition event */
stateMachine.sendEvent(UNUSED_EVENT);
/* no state change.
This will trigger "eventNotAccepted(Message<Events> event)"
in state machine listener,
because UNUSED_EVENT is never mentioned in SM config */
stateMachine.sendEvent(STEP_EVENT);
/* nothing will happen!!!
No state change, as there is no transition
which has current state (SECOND) as source
and STEP_EVENT as transition event,
and no eventNotAccepted call.
But I need it, I want to fail here! */
stateMachine.sendEvent(EXIT_EVENT);
// state will move to EXIT
问题是,当我发送一个属于配置一部分但不适用于当前状态的事件时,没有任何反应。
我不知道状态没有改变是因为守卫还是因为当前状态和我的事件没有转换。
有什么办法可以处理这种情况吗?
最佳答案
要记录不适用于您当前状态的事件,您可以使用 StateMachine 监听器。每次在状态机中传递不满足定义的转换和事件的事件时,都会调用一个方法。
在状态机配置中,您需要覆盖:
public void configure(StateMachineConfigurationConfigurer<State, Event> config) {
config.withConfiguration()
.listener(customListener());
}
并实现您自己的监听器 - 最简单的方法是使用 StateMachineListenerAdapter
并覆盖 eventNotAccepted(Message event)
方法:
private StateMachineListenerAdapter<State, Event> customListener() {
return new StateMachineEventListenerAdapter<State, Event>() {
@Override
public void eventNotAccepted(Message event) {
//LOG which event was not accepted etc.
}
}
}
要记录守卫的结果 - 使用守卫本身的日志消息。
如果你想暴露守卫之外的原因,你可以构造一个键值对并使用StateMachine的扩展上下文来记录守卫名称和事件被拒绝的原因。 上下文可用于构造自定义异常或向调用者代码传达发生的情况。
关于java - 如何处理spring状态机未处理的事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53934031/