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;
}
}

Spring-statemachine给end状态设置action的更多相关文章

  1. 因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 。。。

    因为相同类型的其他实体已具有相同的主键值.在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified&quo ...

  2. (转)Spring Bean Scope 有状态的Bean 无状态的Bean

    有状态会话bean   :每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”:一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束.即每个用户最初都会得到一 ...

  3. 前端技术之:如何在vuex状态管理action异步调用结束后执行UI中的方法

    一.问题的起源 最近在做vue.js项目时,遇到了vuex状态管理action与vue.js方法互相通信.互操作的问题.场景如下图所示: 二.第一种解决方法 例如,我们在页面初始化的时候,需要从服务端 ...

  4. Eureka心跳健康检查机制和Spring boot admin 节点状态一直为DOWN的排查(忽略某一个节点的健康检查)

    https://www.jdon.com/springcloud/eureka-health-monitoring.html 运行阶段执行健康检查的目的是为了从Eureka服务器注册表中识别并删除不可 ...

  5. 使用Spring StateMachine框架实现状态机

    spring statemachine刚出来不久,但是对于一些企业的大型应用的使用还是十分有借鉴意义的. 最近使用了下这个,感觉还是挺好的. 下面举个例子来说下吧: 创建一个Spring Boot的基 ...

  6. struts2 笔记01 登录、常用配置参数、Action访问Servlet API 和设置Action中对象的值、命名空间和乱码处理、Action中包含多个方法如何调用

    Struts2登录 1. 需要注意:Struts2需要运行在JRE1.5及以上版本 2. 在web.xml配置文件中,配置StrutsPrepareAndExecuteFilter或FilterDis ...

  7. tableview 编辑状态设置

    #pragma mark - tableview 编辑状态设置 -(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSI ...

  8. Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法

    Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法 在Action中方法的返回值都是字符串行,一般情况是返回某个JSP,如: return "xx" ...

  9. Spring MVC 程序首页的设置 - 一号门-程序员的工作,程序员的生活(java,python,delphi实战)

    body { font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI ...

随机推荐

  1. Uva 1605 Building for UN【构造法】

    题意:给出n个国家,给它们分配办公室,使得任意两个国家都有一对相邻的格子 看的紫书,最开始看的时候不理解 后来还是搜了题解--- 发现是这样的 比如说5个国家 应该输出 AAAA BBBB CCCC ...

  2. ajax返回数据时,如何将javascript值(通常为对象或数组)转为json字符串

    ajax获取值时,返回的数据为空时 alert后出现 [ ]; 用if语句判断时不为空,此时如何判断返回的数据是否为空.可将返回的值转化为json字符串. JSON.stringify() 方法用于将 ...

  3. Linux重新命名文件夹

    linux 重命名文件和文件夹   linux下重命名文件或文件夹的命令mv既可以重命名,又可以移动文件或文件夹. 例子:将目录A重命名为B mv A B 例子:将/a目录移动到/b下,并重命名为c ...

  4. NodeJS 第一天学习

    NodeJS 第一天学习 严格模式 ECMAScript 5的严格模式是采用具有限制性JavaScript变体的一种方式,从而使代码显示地 脱离"马虎模式/稀松模式/懒散模式"(s ...

  5. puppet介绍与安装

    puppet是什么puppet是一种基于ruby语言开发的Lnux.Unix.windows平台的集中配置管理系统.它使用自有的puppet描述语言,可管理配置文件file.用户user.cron任务 ...

  6. python yield 生成器的介绍(转载)

    您可能听说过,带有 yield 的函数在 Python 中被称之为 generator(生成器),何谓 generator ? 我们先抛开 generator,以一个常见的编程题目来展示 yield ...

  7. 洛谷P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold

    思路大概和其他的题解一样: 从当前字符串最前面,最后面选一个字典序较小的然后拉到一个新的字符串序列中,如果相同就一直往中间扫描直到发现不同为止(一个字符如果被选中之后那么就不可以再次选择了),所以我们 ...

  8. NYIST 531 太空飞行计划

    太空飞行计划 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述        W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利 ...

  9. 洛谷—— P2904 [USACO08MAR]跨河River Crossing

    https://www.luogu.org/problem/show?pid=2904 题目描述 Farmer John is herding his N cows (1 <= N <= ...

  10. STL_算法_Heap算法(堆排)(精)

    C++ Primer 学习中. . . 简单记录下我的学习过程 (代码为主) /***************************************** STL-算法--Heap算法 堆排序 ...