Spring-statemachine给end状态设置action
Spring-statemachine版本:当前最新的1.2.3.RELEASE版本
builder.configureStates()
.withStates()
.initial(generateStateName("task1", Status.INIT))
.state(generateStateName("task1", Status.RUN))
.end(generateStateName("task1", Status.END)); // 没有end(S state, Action<S, E) action)的方法
如上代码,我们想给end状态增加一个action,但是没有相应的api,于是我们把代码改成这样
builder.configureStates()
.withStates()
.initial(generateStateName("task1", Status.INIT))
.state(generateStateName("task1", Status.RUN))
.state(generateStateName("task1", Status.END), context -> { /* do something*/ })
.end(generateStateName("task1", Status.END));
generateStateName方法直接拼接了一个字符串和Status枚举对象的名字:
protected String generateStateName(String taskName, Status status) {
String stateName = taskName + "_" + status.name();
}
结果会发现从run状态进不了end状态,这是为什么呢?
调试源码后,发现org.springframework.statemachine.config.configurers.DefaultStateConfigurer
在配置状态时在这里用到判断:
@Override
public void configure(StateMachineStateBuilder<S, E> builder) throws Exception {
// before passing state datas to builder, update structure
// for missing parent, initial and end state infos.
Collection<StateData<S, E>> stateDatas = new ArrayList<StateData<S, E>>();
for (StateData<S, E> s : incomplete.values()) {
s.setParent(parent);
stateDatas.add(s);
if (s.getState() == initialState) {
s.setInitial(true);
s.setInitialAction(initialAction);
}
if (s.getState() == end) { // 坑爹的判断方法
s.setEnd(true);
}
if (choices.contains(s.getState())) {
s.setPseudoStateKind(PseudoStateKind.CHOICE);
} else if (junctions.contains(s.getState())) {
s.setPseudoStateKind(PseudoStateKind.JUNCTION);
} else if (forks.contains(s.getState())) {
s.setPseudoStateKind(PseudoStateKind.FORK);
} else if (joins.contains(s.getState())) {
s.setPseudoStateKind(PseudoStateKind.JOIN);
} else if (entrys.contains(s.getState())) {
s.setPseudoStateKind(PseudoStateKind.ENTRY);
} else if (exits.contains(s.getState())) {
s.setPseudoStateKind(PseudoStateKind.EXIT);
}
if (s.getState() == history) {
if (History.SHALLOW == historyType) {
s.setPseudoStateKind(PseudoStateKind.HISTORY_SHALLOW);
} else if (History.DEEP == historyType) {
s.setPseudoStateKind(PseudoStateKind.HISTORY_DEEP);
}
}
s.setSubmachine(submachines.get(s.getState()));
s.setSubmachineFactory(submachinefactories.get(s.getState()));
}
builder.addStateData(stateDatas);
}
在上面代码中判断状态:if (s.getState() == end),end是StateMachine < S, E > 泛型中的S,对于上面我写的demo中类型是String。调用state()和end()会生成两个"task1_end"字符串,他们用==判断是不相等的,因此不会被判断为终结状态。。。。。。。
好吧,把生成状态名字改成用一个map保存,然后返回已存在的状态名就行:
protected String generateStateName(String taskName, Status status) {
String stateName = taskName + "_" + status.name();
if (stateNameMap.containsKey(stateName)) {
return stateNameMap.get(stateName);
} else {
stateNameMap.put(stateName, stateName);
return stateName;
}
}