Java 如何处理spring状态机未处理的事件
假设我们有以下状态机配置:Java 如何处理spring状态机未处理的事件,java,spring,spring-statemachine,Java,Spring,Spring Statemachine,假设我们有以下状态机配置: transitions.withExternal() .source(FIRST) .target(SECOND) .event(STEP_EVENT) .and() .source(SECOND) .target(EXIT) .event(EXIT_EVENT) 事件列表:步骤事件、退出事件、未使用事件 stateMachine.init(); // FIRST state stateMachine.
transitions.withExternal()
.source(FIRST)
.target(SECOND)
.event(STEP_EVENT)
.and()
.source(SECOND)
.target(EXIT)
.event(EXIT_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.init();
//第一州
stateMachine.sendEvent(步骤事件);
/*该州排名第二
因为存在以当前状态作为源的转换
和步骤_事件作为转换事件*/
stateMachine.sendEvent(未使用的_事件);
/*没有状态变化。
这将触发“eventNotAccepted(消息事件)”
在状态机侦听器中,
因为SM配置中从未提及未使用的_事件*/
stateMachine.sendEvent(步骤事件);
/*什么都不会发生!!!
没有状态更改,因为没有转换
其中当前状态(秒)作为源
步骤_事件作为转换事件,
并且没有未接受的事件呼叫。
但我需要它,我想在这里失败*/
stateMachine.sendEvent(退出事件);
//州政府将采取行动退出
问题是,当我发送了一个作为配置的一部分但不适用于当前状态的事件时,什么都不会发生
我不知道状态是否因为一个守卫而没有改变,或者因为当前状态和我的事件没有转换
有没有办法处理这种情况?要记录不适用于当前状态的事件,可以使用状态机侦听器。每次在状态机中传递事件时都会调用一个方法,该方法不满足定义的转换和事件 在状态机配置中,您需要覆盖:
public void configure(StateMachineConfigurationConfigurer<State, Event> config) {
config.withConfiguration()
.listener(customListener());
}
对于保护的日志记录结果-使用保护本身中的日志消息
如果要在保护之外公开原因,可以构造一个键值对,并使用状态机的扩展上下文记录保护名称和事件被拒绝的原因。
上下文可用于构造自定义异常或将发生的情况告知调用方代码。已解决!正如经常发生的那样,解决方案太简单,我无法观察到:(。因此,向SM发送事件的方法将布尔值作为返回参数。如果处理和处理事件,则返回true,否则返回false
就是这样-只需检查返回值!谢谢您的回复,但它不是这样工作的。您提到的侦听器将在您发送到SM时被调用,并且在alleventNotAccepted中未处理的事件将在每次事件发送到SM时被调用,但不适用于当前状态-因此SM不接受该事件-这正是您在问题中提出的问题。在提出问题之前,我已经检查过了,它不是这样工作的。您的本地配置中可能存在导致此问题的原因。下面的测试用例证明,已定义事件调用eventNotAccepted,这不适用于当前状态:事实上,它在您的exa中有效示例。我将检查两者之间的区别以及为什么会失败。感谢repo链接!对于简单的情况,这可能足够了,但一点也不灵活。您无法看到哪个事件未被接受(例如,您只有一个布尔值)。另外,您如何在代码中处理此问题?每次发送事件时都使用if/else语句,只是为了检查事件是否被接受?当您有一个集中式侦听器作为选项时,没有必要使用if/else污染…侦听器只捕获SM中根本没有列出的事件。但我一直在寻找处理事件未被列出的情况的方法已处理,因为当前状态不是此事件可以从中处理的状态。这是不正确的。如果您有状态S1、S2和S3以及事件E1、E2,其中E1触发S1和S2之间的转换。如果您在S1中并发送事件E2,则将调用eventNotAccepted。E2列在SM中,但如果您尝试在状态S中使用它,则会将其丢弃1,因为它与SM定义不匹配。
private StateMachineListenerAdapter<State, Event> customListener() {
return new StateMachineEventListenerAdapter<State, Event>() {
@Override
public void eventNotAccepted(Message event) {
//LOG which event was not accepted etc.
}
}
}