Spring Statemachine简记-基础配置(二)
2018-05-17 本文已影响90人
78240024406c
new無语 转载请注明原创出处,谢谢!
配置状态
状态机最基础的状态设定。后面会介绍更复杂的配置示例,但我们首先从简单的事情开始。对于最简单的状态机,你只需使用·EnumStateMachineConfigurerAdapter·并定义可能的状态,选择初始和可选结束状态。
枚举状态
@Configuration
@EnableStateMachine
public class Config1Enums
extends EnumStateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineStateConfigurer<States, Events> states)
throws Exception {
states
.withStates()
//初始状态
.initial(States.S1)
//结束状态
.end(States.SF)
.states(EnumSet.allOf(States.class));
}
}
字符串状态
@Configuration
@EnableStateMachine
public class Config1Strings
extends StateMachineConfigurerAdapter<String, String> {
@Override
public void configure(StateMachineStateConfigurer<String, String> states)
throws Exception {
states
.withStates()
.initial("S1")
.end("SF")
.states(new HashSet<String>(Arrays.asList("S1","S2","S3","S4")));
}
}
分层状态
可以使用多个withStates()
调用来定义分层状态,其中parent()
可以用来指示这些特定状态是某个其他状态的子状态。
state()
states()
当前层次定义状态集,任何初始状态不能在非当前层次定义。
@Configuration
@EnableStateMachine
public class Config2
extends EnumStateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineStateConfigurer<States, Events> states)
throws Exception {
states
.withStates()
.initial(States.S1)
.state(States.S1)
.and()
.withStates()
.parent(States.S1)
.initial(States.S2)
.state(States.S2);
}
}
转换状态配置
支持三种不同类型的转换external
, internal
和local
。
@Configuration
@EnableStateMachine
public class Config3
extends EnumStateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineStateConfigurer<States, Events> states)
throws Exception {
states
.withStates()
.initial(States.S1)
.states(EnumSet.allOf(States.class));
}
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
throws Exception {
transitions
.withExternal()
.source(States.S1).target(States.S2)
.event(Events.E1)
.and()
.withInternal()
.source(States.S2)
.event(Events.E2)
.and()
.withLocal()
.source(States.S2).target(States.S3)
.event(Events.E3);
}
}
保护状态转换
Guards
被用来保护状态转换。
@Configuration
@EnableStateMachine
public class Config4
extends EnumStateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
throws Exception {
transitions
.withExternal()
.source(States.S1).target(States.S2)
.event(Events.E1)
.guard(guard())
.and()
.withExternal()
.source(States.S2).target(States.S3)
.event(Events.E2)
.guardExpression("true");
}
@Bean
public Guard<States, Events> guard() {
return new Guard<States, Events>() {
@Override
public boolean evaluate(StateContext<States, Events> context) {
return true;
}
};
}
}
在上面使用了两种不同类型的防护结构。首先一个简单的
Guard
被创建为一个bean
并添加到状态S1
和状态之间的转换S2
。
其次,一个简单的SPeL
表达式可以用作表达式必须返回一个BOOLEAN
值的校验值。在幕后,这种实现基于SpelExpressionGuard
。
配置动作(actions
)
actions
可以定义为转换状态时同时执行的。
@Configuration
@EnableStateMachine
public class Config51
extends EnumStateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
throws Exception {
transitions
.withExternal()
.source(States.S1)
.target(States.S2)
.event(Events.E1)
.action(action());
}
@Bean
public Action<States, Events> action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
// do something
}
};
}
}
在上面,单个action
关联到状态从S1
转换到S2
。
@Configuration
@EnableStateMachine
public class Config52
extends EnumStateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineStateConfigurer<States, Events> states)
throws Exception {
states
.withStates()
.initial(States.S1, action())
.state(States.S1, action(), null)
.state(States.S2, null, action())
.state(States.S2, action())
.state(States.S3, action(), action());
}
@Bean
public Action<States, Events> action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
// do something
}
};
}
}
一般情况不会对多个状态转换做相同的
action
。
在上面的一个Action
被关联多个状态转换。这里解释一下。
- 定义了初始状态
S1
的action
。 - 为状态
S1
定义了转入动作,并且转出动作为null
。 - 为状态
S2
定义转出行为,并将转入动作置为null
。 - 为状态
S2
定义了一个单一行为action()
。 - 为状态
S3
定义了转入行为以及转出行为。
initial()
中,action()
只在初始化状态时执行。state()
中,action()
,在转入、转出时执行。
转换错误处理
@Configuration
@EnableStateMachine
public class Config53
extends EnumStateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
throws Exception {
transitions
.withExternal()
.source(States.S1)
.target(States.S2)
.event(Events.E1)
.action(action(), errorAction());
}
@Bean
public Action<States, Events> action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
throw new RuntimeException("MyError");
}
};
}
@Bean
public Action<States, Events> errorAction() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
// RuntimeException("MyError") added to context
Exception exception = context.getException();
exception.getMessage();
}
};
}
}
动作状态异常处理
错误处理逻辑可用于转换操作,也可用于为状态行为及其转入和转出定义的操作。
@Configuration
@EnableStateMachine
public class Config55
extends EnumStateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineStateConfigurer<States, Events> states)
throws Exception {
states
.withStates()
.initial(States.S1)
.stateEntry(States.S2, action(), errorAction())
.stateDo(States.S2, action(), errorAction())
.stateExit(States.S2, action(), errorAction())
.state(States.S3);
}
@Bean
public Action<States, Events> action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
throw new RuntimeException("MyError");
}
};
}
@Bean
public Action<States, Events> errorAction() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
// RuntimeException("MyError") added to context
Exception exception = context.getException();
exception.getMessage();
}
};
}
}