15. Using Scopes
对状态机中的作用域的支持非常有限,但可以使用普通的Spring @Scope注释来启用会话作用域。 首先,如果状态机是通过构建器手动构建的,并以@Bean的形式返回上下文,然后通过配置适配器返回。 这两种方法都需要一个@Scope来存在,其中scopeName设置为session,proxyMode设置为ScopedProxyMode.TARGET_CLASS。 下面显示了这两种用例的示例。
请参阅示例第45章,范围如何使用会话范围。
@Configuration
public class Config3 {
@Bean
@Scope(scopeName="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
StateMachine<String, String> stateMachine() throws Exception {
Builder<String, String> builder = StateMachineBuilder.builder();
builder.configureConfiguration()
.withConfiguration()
.autoStartup(true)
.taskExecutor(new SyncTaskExecutor());
builder.configureStates()
.withStates()
.initial("S1")
.state("S2");
builder.configureTransitions()
.withExternal()
.source("S1")
.target("S2")
.event("E1");
StateMachine<String, String> stateMachine = builder.build();
return stateMachine;
}
}
@Configuration
@EnableStateMachine
@Scope(scopeName="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public static class Config4 extends StateMachineConfigurerAdapter<String, String> {
@Override
public void configure(StateMachineConfigurationConfigurer<String, String> config) throws Exception {
config
.withConfiguration()
.autoStartup(true);
}
@Override
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
states
.withStates()
.initial("S1")
.state("S2");
}
@Override
public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
transitions
.withExternal()
.source("S1")
.target("S2")
.event("E1");
}
}
一旦你将状态机限定在会话中,自动装配到一个@Controller将为每个会话提供新的状态机实例。 当HttpSession失效时,状态机将被销毁。
@Controller
public class StateMachineController {
@Autowired
StateMachine<String, String> stateMachine;
@RequestMapping(path="/state", method=RequestMethod.POST)
public HttpEntity<Void> setState(@RequestParam("event") String event) {
stateMachine.sendEvent(event);
return new ResponseEntity<Void>(HttpStatus.ACCEPTED);
}
@RequestMapping(path="/state", method=RequestMethod.GET)
@ResponseBody
public String getState() {
return stateMachine.getState().getId();
}
}
在会话范围中使用状态机需要仔细规划,主要是因为它是一个相对较重的组件
Spring Statemachine poms对Spring MVC类没有任何依赖关系,您将需要使用会话范围。 但是,如果您正在使用Web应用程序,那么您已经直接从Spring MVC或Spring Boot中取得了这些代码。