我在为一个非常简单的场景配置我的 SSM 时遇到问题:
罪魁祸首是触发log_on事件时需要发生的“验证”操作。我重新阅读了 SSM 文档,但不确定这是“fork”、“guard”还是分层配置。
“动作”在这里执行:
@Component
public class LogonValidationAction implements Action<PickStates, PickEvents> {
Logger logger = LogManager.getLogger();
volatile int counter = 0;
@Override
public void execute(StateContext<PickStates, PickEvents> context) {
String eventName = context.getEvent().name();
logger.info("executing {} for event {}", LogonValidationAction.class.getName(), eventName);
// basically, if success, send success, if failure, send failure
// for testing
if(counter % 2 == 0)
context.getStateMachine().sendEvent(PickEvents.logon_sucess);
else
context.getStateMachine().sendEvent(PickEvents.logon_fail);
}
}
我在我的测试中使用“计数器”将流程引导到“失败”(保持登录状态)或“成功”(状态更改为登录状态)。
这是配置:
@Configuration
@EnableStateMachineFactory
public class Config extends EnumStateMachineConfigurerAdapter<PickStates, PickEvents>{
@Autowired
StateMachineListener stateMachineListener;
@Autowired
LogonValidationAction logonValidationAction;
@Override
public void configure(StateMachineStateConfigurer<PickStates, PickEvents> states) throws Exception {
states
.withStates()
.initial(PickStates.logged_off)
.state(PickStates.logged_on)
.states(EnumSet.allOf(PickStates.class));
}
@Override
public void configure(StateMachineTransitionConfigurer<PickStates, PickEvents> transitions) throws Exception {
transitions
.withExternal()
.source(PickStates.logged_off)
.target(PickStates.logged_on)
.event(PickEvents.log_on)
.action(logonValidationAction)
.and()
.withExternal()
.source(PickStates.logged_on)
.target(PickStates.logged_off)
.event(PickEvents.log_off);
}
@Override
public void configure(StateMachineConfigurationConfigurer<PickStates, PickEvents> config) throws Exception {
config
.withConfiguration()
.autoStartup(true)
.listener(stateMachineListener);
}
}
这是失败的测试(当操作触发 logon_fail 事件时期望“logged_off”):
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
public class EzpickStateMachineTest {
Logger logger = LogManager.getLogger();
@Autowired
StateMachineFactory<PickStates, PickEvents> stateMachineFactory;
// for testing so can toggle success/failure when logging in
@Autowired
LogonValidationAction logonValidationAction;
@Test
public void failLogon() throws Exception {
StateMachine<PickStates, PickEvents> stateMachine = stateMachineFactory.getStateMachine();
stateMachine.start();
// when sm starts, state is 'logged_off'
assertThat(stateMachine.getState().getId().name(), is(PickStates.logged_off.name()));
// odd numbers fire 'failure' event
logonValidationAction.setCounter(1);
stateMachine.sendEvent(PickEvents.log_on);
// if logon fails, state is 'logged_off'
assertThat(stateMachine.getState().getId().name(), is(PickStates.logged_off.name()));
}
}