共计 17594 个字符,预计需要花费 44 分钟才能阅读完成。
1、讲讲复杂流程的需求
除了上面文章里面提到的一根筋状态机流程,实际的企业应用中状态机的流程会更加复杂,而我们最常用到的就是 choice。它类似于 java 的 if 语句,作为条件判断的分支而存在,让我们先看一张图:
这张图表现的是一个表单(form)的整个状态流程:
创建初始的空白表单(BLANK_FORM)
填写 (WRITE) 表单,成为填充完表单(FULL_FORM)
检查 (CHEKC) 表单
如果是表单名(formName)不为 null,表单成为待提交表单(CONFIRM_FROM)
提交(SUBMIT)表单,成为成功提交表单(SUCCESS_FORM)
检查(CHECK)表单
如果表单名为 null,表单成为待处理表单(DEAL_FORM), 修改 formName
处理 (DEAL) 表单
如果表单名还是 null 或者里面有个“坏”字,表单状态变成废单(FAILED_FORM)
如果表单名称没问题,表单状态变成填充完表单状态(FULL_FORM), 重新走流程
大家不要在意这个例子的幼稚,毕竟它还是能用简单的方式体现出流程的复杂性(这话多么的辩证统一)。它有判断分支(还有两个),还有流程的循环,还有分支判断后的直接失败和分支判断后的后续环节,后面我们会在代码中告诉大家这里面需要注意的东西。
2、代码实现
先上状态机的四件套:States,Events,Builder 和 EventConfig(spring statemachine 还是蛮简单的,来来回回就这几样东西)
public enum ComplexFormStates {
BLANK_FORM, // 空白表单
FULL_FORM, // 填写完表单
CHECK_CHOICE,// 表单校验判断
DEAL_CHOICE,// 表单处理校验
DEAL_FORM,// 待处理表单
CONFIRM_FORM, // 校验完表单
SUCCESS_FORM,// 成功表单
FAILED_FORM// 失败表单
}
注意一点,choice 判断分支本身也是一种状态,要声明出来,这里是 CHECK_CHOICE 和 DEAL_CHOICE
public enum ComplexFormEvents {
WRITE, // 填写
CHECK,// 校验
DEAL,// 处理
SUBMIT // 提交
}
同样的分支事件也要声明,这里是 CHECK 和 DEAL。
大头是 MachineBuilder,这个代码就比较多,大家最好对照着上面这张图来看,会比较清晰
/**
- 复杂订单状态机构建器
*/
@Component
public class ComplexFormStateMachineBuilder {
private final static String MACHINEID = "complexFormMachine";
/**
* 构建状态机
*
* @param beanFactory
* @return
* @throws Exception
*/
public StateMachine<ComplexFormStates, ComplexFormEvents> build(BeanFactory beanFactory) throws Exception {StateMachineBuilder.Builder<ComplexFormStates, ComplexFormEvents> builder = StateMachineBuilder.builder();
System.out.println("构建复杂表单状态机");
builder.configureConfiguration()
.withConfiguration()
.machineId(MACHINEID)
.beanFactory(beanFactory);
builder.configureStates()
.withStates()
.initial(ComplexFormStates.BLANK_FORM)
.choice(ComplexFormStates.CHECK_CHOICE)
.choice(ComplexFormStates.DEAL_CHOICE)
.states(EnumSet.allOf(ComplexFormStates.class));
builder.configureTransitions()
.withExternal()
.source(ComplexFormStates.BLANK_FORM).target(ComplexFormStates.FULL_FORM)
.event(ComplexFormEvents.WRITE)
.and()
.withExternal()
.source(ComplexFormStates.FULL_FORM).target(ComplexFormStates.CHECK_CHOICE)
.event(ComplexFormEvents.CHECK)
.and()
.withChoice()
.source(ComplexFormStates.CHECK_CHOICE)
.first(ComplexFormStates.CONFIRM_FORM, new ComplexFormCheckChoiceGuard())
.last(ComplexFormStates.DEAL_FORM)
.and()
.withExternal()
.source(ComplexFormStates.CONFIRM_FORM).target(ComplexFormStates.SUCCESS_FORM)
.event(ComplexFormEvents.SUBMIT)
.and()
.withExternal()
.source(ComplexFormStates.DEAL_FORM).target(ComplexFormStates.DEAL_CHOICE)
.event(ComplexFormEvents.DEAL)
.and()
.withChoice()
.source(ComplexFormStates.DEAL_CHOICE)
.first(ComplexFormStates.FULL_FORM, new ComplexFormDealChoiceGuard())
.last(ComplexFormStates.FAILED_FORM);
return builder.build();}
}
这里面出现了几个新东西,要说一下:
在 configureStates 时,要把每个分支都要写上去,我之前写了 ComplexFormStates.CHECK_CHOICE,忘了写 DEAL_CHOICE,后面的 choice 就不执行,搞得我找了很久,大家要注意(是的,我犯的就是这种简单弱智的错误,我还找了很久)
在我们熟悉的 withExternal 之后,我们迎来了为 choice 专门准备的 withChoice()和跟随它的 first(),last()。这两个代表的就是分支判断时 TRUE 和 FALSE 的状态流程去处,这里面涉及到的一个问题就是,TRUE 和 FALSE 的判断条件是什么呢,根据啥来判断呢?
Guard 就承担了这个判断的功能,看名字似乎不像。它在 spring statemachine 本来是用来保护这个状态跳转过程的,所以用 guard,但在 choice 里面,它就是作为判断代码而存在的,代码如下:
public class ComplexFormCheckChoiceGuard implements Guard<ComplexFormStates, ComplexFormEvents> {
@Override
public boolean evaluate(StateContext<ComplexFormStates, ComplexFormEvents> context) {
boolean returnValue = false;
Form form = context.getMessage().getHeaders().get("form", Form.class);
if (form.formName == null) {returnValue = false;} else {returnValue = true;}
return returnValue;
}
}
它只 implements 一个方法 evaluate(),返回 boolean 类型,所以很适合做这个判断的功能。另外一个 DEAL_CHOICE 的 gurad 代码是这样的
public class ComplexFormDealChoiceGuard implements Guard<ComplexFormStates, ComplexFormEvents> {
@Override
public boolean evaluate(StateContext<ComplexFormStates, ComplexFormEvents> context) {System.out.println("ComplexFormDealChoiceGuard!!!!!!!!!!!!!");
boolean returnValue = false;
Form form = context.getMessage().getHeaders().get("form", Form.class);
if ((form.formName == null)||(form.formName.indexOf("坏") > -1)) {returnValue = false;} else {returnValue = true;}
System.out.println(form.toString()+"is"+returnValue);
return returnValue;
}
}
还有四件套的最后一个 EventConfig:
@WithStateMachine(id=”complexFormMachine”)
public class ComplexFormEventConfig {
private Logger logger = LoggerFactory.getLogger(getClass());
/**
* 当前状态 BLANK_FORM
*/
@OnTransition(target = "BLANK_FORM")
public void create() {logger.info("--- 空白复杂表单 ---");
}
@OnTransition(source = "BLANK_FORM", target = "FULL_FORM")
public void write(Message<ComplexFormEvents> message) {System.out.println("传递的参数:" + message.getHeaders().get("form"));
logger.info("--- 填写完复杂表单 ---");
}
@OnTransition(source = "FULL_FORM", target = "CHECK_CHOICE")
public void check(Message<ComplexFormEvents> message) {System.out.println("传递的参数:" + message.getHeaders().get("form").toString());
logger.info("--- 校验复杂表单 ---");
}
// 不会执行
@OnTransition(source = "CHECK_CHOICE", target = "CONFIRM_FORM")
public void check2confirm(Message<ComplexFormEvents> message) {System.out.println("传递的参数:" + message.getHeaders().get("form").toString());
logger.info("--- 校验表单到待提交表单(choice true)---");
}
// 不会执行
@OnTransition(source = "CHECK_CHOICE", target = "DEAL_FORM")
public void check2deal(Message<ComplexFormEvents> message) {System.out.println("传递的参数:" + message.getHeaders().get("form").toString());
logger.info("--- 校验表单到待提交表单(choice false)---");
}
@OnTransition(source = "DEAL_FORM", target = "DEAL_CHOICE")
public void deal(Message<ComplexFormEvents> message) {System.out.println("传递的参数:" + message.getHeaders().get("form").toString());
logger.info("--- 处理复杂表单 ---");
}
// 不会执行
@OnTransition(source = "DEAL_CHOICE", target = "FAILED_FORM")
public void deal2fail(Message<ComplexFormEvents> message) {System.out.println("传递的参数:" + message.getHeaders().get("form").toString());
logger.info("--- 处理复杂表单失败(choice false)---");
}
// 不会执行
@OnTransition(source = "DEAL_CHOICE", target = "FULL_FORM")
public void deal2full(Message<ComplexFormEvents> message) {System.out.println("传递的参数:" + message.getHeaders().get("form").toString());
logger.info("--- 处理复杂表单到重新填写表单(choice true)---");
}
/**
* CONFIRM_FORM->SUCCESS_FORM 执行的动作
*/
@OnTransition(source = "CONFIRM_FORM", target = "SUCCESS_FORM")
public void submit(Message<ComplexFormEvents> message) {System.out.println("传递的参数:" + message.getHeaders().get("form").toString());
logger.info("--- 表单提交成功 ---");
}
}
这边的代码没有任何特别的地方,唯一需要需要注意的是我标注的不会执行的这几个方法。因为在 choice 判断的时候,从一个状态转变到另外一个状态时,是不会在 eventConfig 触发方法的,比如这个方法:
// 不会执行
@OnTransition(source = "CHECK_CHOICE", target = "CONFIRM_FORM")
public void check2confirm(Message<ComplexFormEvents> message) {System.out.println("传递的参数:" + message.getHeaders().get("form").toString());
logger.info("--- 校验表单到待提交表单(choice true)---");
}
我定义了如果用户从 CHECK_CHOICE 状态如果判断后变成 CONFIRM_FORM,执行 check2confirm 方法,但可惜,状态的确变化了,但这个方法不会执行,只有在做判断的时候会执行 ComplexFormCheckChoiceGuard 的 evaluate()。这就有个问题,在实际运行中,我们的确会需要在 choice 做出判断状态改变的时候要做些业务处理,比如表单 check 成功后需要通知后续人员来处理什么的,这该怎么办呢?
简单除暴第一招,直接在 gurad 里面处理。这种方法其实没有任何问题,因为既然判断的业务代码在这里面,我们把判断完成后需要做的事也在这里写完不就行了。但是,本着无关的业务能解耦就解耦的原则,我们还有一个办法
漂亮解耦第二招,写个 action。下面介绍下这个 action。
action,看这个名字就知道是要搞事情的,之前我们把业务代码都是写到 eventConfig 的方法里面,但其实可以不怎么干,我们完全可以在每个状态变化的时候独立写一个 action,这样的话就能做到业务的互不打扰。不如下面这段:
.withChoice()
.source(ComplexFormStates.CHECK_CHOICE)
.first(ComplexFormStates.CONFIRM_FORM, new ComplexFormCheckChoiceGuard(),new ComplexFormChoiceAction())
.last(ComplexFormStates.DEAL_FORM,new ComplexFormChoiceAction())
.and()
这是 builder 里面的代码片段,我们直接把 action 插入进来,在状态变化的时候就能在 action 里面处理了,下面是这个 action
的代码:
public class ComplexFormChoiceAction implements Action<ComplexFormStates, ComplexFormEvents> {
@Override
public void execute(StateContext<ComplexFormStates, ComplexFormEvents> context) {System.out.println("into ComplexFormChoiceAction");
Form form = context.getMessage().getHeaders().get("form", Form.class);
System.out.println(form);
System.out.println(context.getStateMachine().getState());
}
}
这里面只有一个 execute 的方法,简单明了,我们需要的参数通过 context 传递,其实还是 message,这样的话,不同业务用不同的 action 就行了,我们再回头看 builder 里面插入 action 的地方:
.first(ComplexFormStates.CONFIRM_FORM, new ComplexFormCheckChoiceGuard(),new ComplexFormChoiceAction(),new ComplexFormChoiceAction())
action 可以多个插入,也就是有多少单独的业务需要在这里面处理都行,其实回过头来,不止在 withChoice()里面可以,之前的 withExternal()也是可以的,看代码:
.withExternal()
.source(ComplexFormStates.FULL_FORM).target(ComplexFormStates.CHECK_CHOICE)
.event(ComplexFormEvents.CHECK)
.action(new ComplexFormChoiceAction(),new ComplexFormChoiceAction())
.guard(new ComplexFormCheckChoiceGuard())
.and()
action 可以插入多个,但 guard 在这里恢复了本来的作用,保护状态变化,所以只能插入一个。
3、在 controller 里面看结果
最后,我们还是需要看下运行的结果,我准备了三个流程:
check 成功,成为 SUCCESS_FORM
check 失败,deal 成功,回到 FULL_FORM
check 失败,deal 失败,成为 FAILED_FORM
对应的是 form1,form2 和 form3,看代码:
@Autowired
private ComplexFormStateMachineBuilder complexFormStateMachineBuilder;
……
@RequestMapping(“/testComplexFormState”)
public void testComplexFormState() throws Exception {StateMachine<ComplexFormStates, ComplexFormEvents> stateMachine = complexFormStateMachineBuilder.build(beanFactory);
System.out.println(stateMachine.getId());
Form form1 = new Form();
form1.setId("111");
form1.setFormName(null);
Form form2 = new Form();
form2.setId("222");
form2.setFormName("好的表单");
Form form3 = new Form();
form3.setId("333");
form3.setFormName(null);
// 创建流程
System.out.println("-------------------form1------------------");
stateMachine.start();
Message message = MessageBuilder.withPayload(ComplexFormEvents.WRITE).setHeader("form", form1).build();
stateMachine.sendEvent(message);
System.out.println("当前状态:" + stateMachine.getState().getId());
message = MessageBuilder.withPayload(ComplexFormEvents.CHECK).setHeader("form", form1).build();
stateMachine.sendEvent(message);
System.out.println("当前状态:" + stateMachine.getState().getId());
message = MessageBuilder.withPayload(ComplexFormEvents.DEAL).setHeader("form", form1).build();
stateMachine.sendEvent(message);
System.out.println("当前状态:" + stateMachine.getState().getId());
message = MessageBuilder.withPayload(ComplexFormEvents.SUBMIT).setHeader("form", form1).build();
stateMachine.sendEvent(message);
System.out.println("最终状态:" + stateMachine.getState().getId());
System.out.println("-------------------form2------------------");
stateMachine = complexFormStateMachineBuilder.build(beanFactory);
stateMachine.start();
message = MessageBuilder.withPayload(ComplexFormEvents.WRITE).setHeader("form", form2).build();
stateMachine.sendEvent(message);
System.out.println("当前状态:" + stateMachine.getState().getId());
message = MessageBuilder.withPayload(ComplexFormEvents.CHECK).setHeader("form", form2).build();
stateMachine.sendEvent(message);
System.out.println("当前状态:" + stateMachine.getState().getId());
message = MessageBuilder.withPayload(ComplexFormEvents.DEAL).setHeader("form", form2).build();
stateMachine.sendEvent(message);
System.out.println("当前状态:" + stateMachine.getState().getId());
message = MessageBuilder.withPayload(ComplexFormEvents.SUBMIT).setHeader("form", form2).build();
stateMachine.sendEvent(message);
System.out.println("最终状态:" + stateMachine.getState().getId());
System.out.println("-------------------form3------------------");
stateMachine = complexFormStateMachineBuilder.build(beanFactory);
stateMachine.start();
message = MessageBuilder.withPayload(ComplexFormEvents.WRITE).setHeader("form", form3).build();
stateMachine.sendEvent(message);
System.out.println("当前状态:" + stateMachine.getState().getId());
message = MessageBuilder.withPayload(ComplexFormEvents.CHECK).setHeader("form", form3).build();
stateMachine.sendEvent(message);
System.out.println("当前状态:" + stateMachine.getState().getId());
form3.setFormName("好的表单");
message = MessageBuilder.withPayload(ComplexFormEvents.DEAL).setHeader("form", form3).build();
stateMachine.sendEvent(message);
System.out.println("当前状态:" + stateMachine.getState().getId());
message = MessageBuilder.withPayload(ComplexFormEvents.SUBMIT).setHeader("form", form3).build();
stateMachine.sendEvent(message);
message = MessageBuilder.withPayload(ComplexFormEvents.CHECK).setHeader("form", form3).build();
stateMachine.sendEvent(message);
System.out.println("当前状态:" + stateMachine.getState().getId());
message = MessageBuilder.withPayload(ComplexFormEvents.SUBMIT).setHeader("form", form3).build();
stateMachine.sendEvent(message);
System.out.println("最终状态:" + stateMachine.getState().getId());
}
……
看 console 的结果就知道正确与否
构建复杂表单状态机
complexFormMachine
——————-form1——————
2019-05-13 18:07:19.364 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 空白复杂表单 —
2019-05-13 18:07:19.368 INFO 6188 — [nio-9991-exec-1] o.s.s.support.LifecycleObjectSupport : started org.springframework.statemachine.support.DefaultStateMachineExecutor@16603576
2019-05-13 18:07:19.369 INFO 6188 — [nio-9991-exec-1] o.s.s.support.LifecycleObjectSupport : started CONFIRM_FORM BLANK_FORM FAILED_FORM FULL_FORM SUCCESS_FORM DEAL_FORM DEAL_CHOICE CHECK_CHOICE / BLANK_FORM / uuid=2aa87c74-dd28-4790-9722-d04657eaf046 / id=complexFormMachine
传递的参数:Form [id=111, formName=null]
2019-05-13 18:07:19.381 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 填写完复杂表单 —
当前状态:FULL_FORM
传递的参数:Form [id=111, formName=null]
2019-05-13 18:07:19.386 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 校验复杂表单 —
ComplexFormCheckChoiceGuard!!!!!!!!!!!!!
Form [id=111, formName=null] is false
into ComplexFormChoiceAction
Form [id=111, formName=null]
ObjectState [getIds()=[FULL_FORM], getClass()=class org.springframework.statemachine.state.ObjectState, hashCode()=381700599, toString()=AbstractState [id=FULL_FORM, pseudoState=null, deferred=[], entryActions=[], exitActions=[], stateActions=[], regions=[], submachine=null]]
当前状态:DEAL_FORM
传递的参数:Form [id=111, formName=null]
2019-05-13 18:07:19.389 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 处理复杂表单 —
ComplexFormDealChoiceGuard!!!!!!!!!!!!!
Form [id=111, formName=null] is false
into ComplexFormChoiceAction
Form [id=111, formName=null]
ObjectState [getIds()=[DEAL_FORM], getClass()=class org.springframework.statemachine.state.ObjectState, hashCode()=980487842, toString()=AbstractState [id=DEAL_FORM, pseudoState=null, deferred=[], entryActions=[], exitActions=[], stateActions=[], regions=[], submachine=null]]
当前状态:FAILED_FORM
最终状态:FAILED_FORM
——————-form2——————
构建复杂表单状态机
2019-05-13 18:07:19.394 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 空白复杂表单 —
2019-05-13 18:07:19.394 INFO 6188 — [nio-9991-exec-1] o.s.s.support.LifecycleObjectSupport : started org.springframework.statemachine.support.DefaultStateMachineExecutor@51adbaad
2019-05-13 18:07:19.394 INFO 6188 — [nio-9991-exec-1] o.s.s.support.LifecycleObjectSupport : started CONFIRM_FORM BLANK_FORM FAILED_FORM FULL_FORM SUCCESS_FORM DEAL_FORM DEAL_CHOICE CHECK_CHOICE / BLANK_FORM / uuid=fa133ea8-bf48-437e-ae35-dc7aa616a23c / id=complexFormMachine
传递的参数:Form [id=222, formName= 好的表单]
2019-05-13 18:07:19.395 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 填写完复杂表单 —
当前状态:FULL_FORM
传递的参数:Form [id=222, formName= 好的表单]
2019-05-13 18:07:19.396 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 校验复杂表单 —
ComplexFormCheckChoiceGuard!!!!!!!!!!!!!
Form [id=222, formName= 好的表单] is true
into ComplexFormChoiceAction
Form [id=222, formName= 好的表单]
ObjectState [getIds()=[FULL_FORM], getClass()=class org.springframework.statemachine.state.ObjectState, hashCode()=249611509, toString()=AbstractState [id=FULL_FORM, pseudoState=null, deferred=[], entryActions=[], exitActions=[], stateActions=[], regions=[], submachine=null]]
当前状态:CONFIRM_FORM
当前状态:CONFIRM_FORM
传递的参数:Form [id=222, formName= 好的表单]
2019-05-13 18:07:19.399 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 表单提交成功 —
最终状态:SUCCESS_FORM
——————-form3——————
构建复杂表单状态机
2019-05-13 18:07:19.404 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 空白复杂表单 —
2019-05-13 18:07:19.405 INFO 6188 — [nio-9991-exec-1] o.s.s.support.LifecycleObjectSupport : started org.springframework.statemachine.support.DefaultStateMachineExecutor@6f12d1a
2019-05-13 18:07:19.406 INFO 6188 — [nio-9991-exec-1] o.s.s.support.LifecycleObjectSupport : started CONFIRM_FORM BLANK_FORM FAILED_FORM FULL_FORM SUCCESS_FORM DEAL_FORM DEAL_CHOICE CHECK_CHOICE / BLANK_FORM / uuid=03e8c891-eedc-4922-811c-ab375a1e70ae / id=complexFormMachine
传递的参数:Form [id=333, formName=null]
2019-05-13 18:07:19.409 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 填写完复杂表单 —
当前状态:FULL_FORM
传递的参数:Form [id=333, formName=null]
2019-05-13 18:07:19.410 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 校验复杂表单 —
ComplexFormCheckChoiceGuard!!!!!!!!!!!!!
Form [id=333, formName=null] is false
into ComplexFormChoiceAction
Form [id=333, formName=null]
ObjectState [getIds()=[FULL_FORM], getClass()=class org.springframework.statemachine.state.ObjectState, hashCode()=608638875, toString()=AbstractState [id=FULL_FORM, pseudoState=null, deferred=[], entryActions=[], exitActions=[], stateActions=[], regions=[], submachine=null]]
当前状态:DEAL_FORM
传递的参数:Form [id=333, formName= 好的表单]
2019-05-13 18:07:19.412 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 处理复杂表单 —
ComplexFormDealChoiceGuard!!!!!!!!!!!!!
Form [id=333, formName= 好的表单] is true
into ComplexFormChoiceAction
Form [id=333, formName= 好的表单]
ObjectState [getIds()=[DEAL_FORM], getClass()=class org.springframework.statemachine.state.ObjectState, hashCode()=1203626264, toString()=AbstractState [id=DEAL_FORM, pseudoState=null, deferred=[], entryActions=[], exitActions=[], stateActions=[], regions=[], submachine=null]]
当前状态:FULL_FORM
传递的参数:Form [id=333, formName= 好的表单]
2019-05-13 18:07:19.413 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 校验复杂表单 —
ComplexFormCheckChoiceGuard!!!!!!!!!!!!!
Form [id=333, formName= 好的表单] is true
into ComplexFormChoiceAction
Form [id=333, formName= 好的表单]
ObjectState [getIds()=[FULL_FORM], getClass()=class org.springframework.statemachine.state.ObjectState, hashCode()=608638875, toString()=AbstractState [id=FULL_FORM, pseudoState=null, deferred=[], entryActions=[], exitActions=[], stateActions=[], regions=[], submachine=null]]
当前状态:CONFIRM_FORM
传递的参数:Form [id=333, formName= 好的表单]
2019-05-13 18:07:19.415 INFO 6188 — [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : — 表单提交成功 —
最终状态:SUCCESS_FORM
大家可以跑一下,对照状态机的流程图,看下结果。
4、继续废话
其实 spring statemachine 写到这里,基本上已经可以上手去做企业开发了。当然,spring statemachine 里面还有很多其他的东西,大部分是处理复杂状态机流程的,以后有机会我们再展开讲。
源代码地址