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;
    }
}
posted @ 2017-03-25 23:02  -六月飞雪-  阅读(593)  评论(0编辑  收藏  举报