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.
    }
  }
}