摘要:講講復(fù)雜流程的需求除了上面文章里面提到的一根筋狀態(tài)機(jī)流程,實(shí)際的企業(yè)應(yīng)用中狀態(tài)機(jī)的流程會(huì)更加復(fù)雜,而我們最常用到的就是。當(dāng)然,里面還有很多其他的東西,大部分是處理復(fù)雜狀態(tài)機(jī)流程的,以后有機(jī)會(huì)我們?cè)僬归_講。
1、講講復(fù)雜流程的需求
除了上面文章里面提到的一根筋狀態(tài)機(jī)流程,實(shí)際的企業(yè)應(yīng)用中狀態(tài)機(jī)的流程會(huì)更加復(fù)雜,而我們最常用到的就是choice。它類似于java的if語(yǔ)句,作為條件判斷的分支而存在,讓我們先看一張圖:
這張圖表現(xiàn)的是一個(gè)表單(form)的整個(gè)狀態(tài)流程:
創(chuàng)建初始的空白表單( BLANK_FORM)
填寫(WRITE)表單,成為填充完表單(FULL_FORM)
檢查(CHEKC)表單
如果是表單名(formName)不為null,表單成為待提交表單(CONFIRM_FROM)
提交(SUBMIT)表單,成為成功提交表單(SUCCESS_FORM)
檢查(CHECK)表單
如果表單名為null,表單成為待處理表單(DEAL_FORM),修改formName
處理(DEAL)表單
如果表單名還是null或者里面有個(gè)“壞”字,表單狀態(tài)變成廢單(FAILED_FORM)
如果表單名稱沒(méi)問(wèn)題,表單狀態(tài)變成填充完表單狀態(tài)(FULL_FORM),重新走流程
大家不要在意這個(gè)例子的幼稚,畢竟它還是能用簡(jiǎn)單的方式體現(xiàn)出流程的復(fù)雜性(這話多么的辯證統(tǒng)一)。它有判斷分支(還有兩個(gè)),還有流程的循環(huán),還有分支判斷后的直接失敗和分支判斷后的后續(xù)環(huán)節(jié),后面我們會(huì)在代碼中告訴大家這里面需要注意的東西。
2、代碼實(shí)現(xiàn)
先上狀態(tài)機(jī)的四件套:States,Events,Builder和EventConfig(spring statemachine還是蠻簡(jiǎn)單的,來(lái)來(lái)回回就這幾樣?xùn)|西)
public enum ComplexFormStates {
BLANK_FORM, // 空白表單 FULL_FORM, // 填寫完表單 CHECK_CHOICE,//表單校驗(yàn)判斷 DEAL_CHOICE,//表單處理校驗(yàn) DEAL_FORM,//待處理表單 CONFIRM_FORM, // 校驗(yàn)完表單 SUCCESS_FORM,// 成功表單 FAILED_FORM//失敗表單
}
注意一點(diǎn),choice判斷分支本身也是一種狀態(tài),要聲明出來(lái),這里是CHECK_CHOICE和DEAL_CHOICE
public enum ComplexFormEvents {
WRITE, // 填寫 CHECK,//校驗(yàn) DEAL,//處理 SUBMIT // 提交
}
同樣的分支事件也要聲明,這里是CHECK和DEAL。
大頭是MachineBuilder,這個(gè)代碼就比較多,大家最好對(duì)照著上面這張圖來(lái)看,會(huì)比較清晰
/**
復(fù)雜訂單狀態(tài)機(jī)構(gòu)建器
*/
@Component
public class ComplexFormStateMachineBuilder {
private final static String MACHINEID = "complexFormMachine"; /** * 構(gòu)建狀態(tài)機(jī) * * @param beanFactory * @return * @throws Exception */ public StateMachinebuild(BeanFactory beanFactory) throws Exception { StateMachineBuilder.Builder builder = StateMachineBuilder.builder(); System.out.println("構(gòu)建復(fù)雜表單狀態(tài)機(jī)"); 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(); }
}
這里面出現(xiàn)了幾個(gè)新東西,要說(shuō)一下:
在configureStates時(shí),要把每個(gè)分支都要寫上去,我之前寫了ComplexFormStates.CHECK_CHOICE,忘了寫DEAL_CHOICE,后面的choice就不執(zhí)行,搞得我找了很久,大家要注意(是的,我犯的就是這種簡(jiǎn)單弱智的錯(cuò)誤,我還找了很久)
在我們熟悉的withExternal之后,我們迎來(lái)了為choice專門準(zhǔn)備的withChoice()和跟隨它的first(),last()。這兩個(gè)代表的就是分支判斷時(shí)TRUE和FALSE的狀態(tài)流程去處,這里面涉及到的一個(gè)問(wèn)題就是,TRUE和FALSE的判斷條件是什么呢,根據(jù)啥來(lái)判斷呢?
Guard就承擔(dān)了這個(gè)判斷的功能,看名字似乎不像。它在spring statemachine本來(lái)是用來(lái)保護(hù)這個(gè)狀態(tài)跳轉(zhuǎn)過(guò)程的,所以用guard,但在choice里面,它就是作為判斷代碼而存在的,代碼如下:
public class ComplexFormCheckChoiceGuard implements Guard
@Override public boolean evaluate(StateContextcontext) { boolean returnValue = false; Form form = context.getMessage().getHeaders().get("form", Form.class); if (form.formName == null) { returnValue = false; } else { returnValue = true; } return returnValue; }
}
它只implements一個(gè)方法evaluate(),返回boolean類型,所以很適合做這個(gè)判斷的功能。另外一個(gè)DEAL_CHOICE的gurad代碼是這樣的
public class ComplexFormDealChoiceGuard implements Guard
@Override public boolean evaluate(StateContextcontext) { 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; }
}
還有四件套的最后一個(gè)EventConfig:
@WithStateMachine(id="complexFormMachine")
public class ComplexFormEventConfig {
private Logger logger = LoggerFactory.getLogger(getClass());
/** * 當(dāng)前狀態(tài)BLANK_FORM */ @OnTransition(target = "BLANK_FORM") public void create() { logger.info("---空白復(fù)雜表單---"); } @OnTransition(source = "BLANK_FORM", target = "FULL_FORM") public void write(Messagemessage) { System.out.println("傳遞的參數(shù):" + message.getHeaders().get("form")); logger.info("---填寫完復(fù)雜表單---"); } @OnTransition(source = "FULL_FORM", target = "CHECK_CHOICE") public void check(Message message) { System.out.println("傳遞的參數(shù):" + message.getHeaders().get("form").toString()); logger.info("---校驗(yàn)復(fù)雜表單---"); }
//不會(huì)執(zhí)行
@OnTransition(source = "CHECK_CHOICE", target = "CONFIRM_FORM") public void check2confirm(Messagemessage) { System.out.println("傳遞的參數(shù):" + message.getHeaders().get("form").toString()); logger.info("---校驗(yàn)表單到待提交表單(choice true)---"); }
//不會(huì)執(zhí)行
@OnTransition(source = "CHECK_CHOICE", target = "DEAL_FORM") public void check2deal(Messagemessage) { System.out.println("傳遞的參數(shù):" + message.getHeaders().get("form").toString()); logger.info("---校驗(yàn)表單到待提交表單(choice false)---"); } @OnTransition(source = "DEAL_FORM", target = "DEAL_CHOICE") public void deal(Message message) { System.out.println("傳遞的參數(shù):" + message.getHeaders().get("form").toString()); logger.info("---處理復(fù)雜表單---"); } //不會(huì)執(zhí)行 @OnTransition(source = "DEAL_CHOICE", target = "FAILED_FORM") public void deal2fail(Message message) { System.out.println("傳遞的參數(shù):" + message.getHeaders().get("form").toString()); logger.info("---處理復(fù)雜表單失敗(choice false)---"); } //不會(huì)執(zhí)行 @OnTransition(source = "DEAL_CHOICE", target = "FULL_FORM") public void deal2full(Message message) { System.out.println("傳遞的參數(shù):" + message.getHeaders().get("form").toString()); logger.info("---處理復(fù)雜表單到重新填寫表單(choice true)---"); } /** * CONFIRM_FORM->SUCCESS_FORM 執(zhí)行的動(dòng)作 */ @OnTransition(source = "CONFIRM_FORM", target = "SUCCESS_FORM") public void submit(Message message) { System.out.println("傳遞的參數(shù):" + message.getHeaders().get("form").toString()); logger.info("---表單提交成功---"); }
}
這邊的代碼沒(méi)有任何特別的地方,唯一需要需要注意的是我標(biāo)注的不會(huì)執(zhí)行的這幾個(gè)方法。因?yàn)樵赾hoice判斷的時(shí)候,從一個(gè)狀態(tài)轉(zhuǎn)變到另外一個(gè)狀態(tài)時(shí),是不會(huì)在eventConfig觸發(fā)方法的,比如這個(gè)方法:
//不會(huì)執(zhí)行
@OnTransition(source = "CHECK_CHOICE", target = "CONFIRM_FORM") public void check2confirm(Messagemessage) { System.out.println("傳遞的參數(shù):" + message.getHeaders().get("form").toString()); logger.info("---校驗(yàn)表單到待提交表單(choice true)---"); }
我定義了如果用戶從CHECK_CHOICE狀態(tài)如果判斷后變成CONFIRM_FORM,執(zhí)行check2confirm方法,但可惜,狀態(tài)的確變化了,但這個(gè)方法不會(huì)執(zhí)行,只有在做判斷的時(shí)候會(huì)執(zhí)行ComplexFormCheckChoiceGuard的evaluate()。這就有個(gè)問(wèn)題,在實(shí)際運(yùn)行中,我們的確會(huì)需要在choice做出判斷狀態(tài)改變的時(shí)候要做些業(yè)務(wù)處理,比如表單check成功后需要通知后續(xù)人員來(lái)處理什么的,這該怎么辦呢?
簡(jiǎn)單除暴第一招,直接在gurad里面處理。這種方法其實(shí)沒(méi)有任何問(wèn)題,因?yàn)榧热慌袛嗟臉I(yè)務(wù)代碼在這里面,我們把判斷完成后需要做的事也在這里寫完不就行了。但是,本著無(wú)關(guān)的業(yè)務(wù)能解耦就解耦的原則,我們還有一個(gè)辦法
漂亮解耦第二招,寫個(gè)action。下面介紹下這個(gè)action。
action,看這個(gè)名字就知道是要搞事情的,之前我們把業(yè)務(wù)代碼都是寫到eventConfig的方法里面,但其實(shí)可以不怎么干,我們完全可以在每個(gè)狀態(tài)變化的時(shí)候獨(dú)立寫一個(gè)action,這樣的話就能做到業(yè)務(wù)的互不打擾。不如下面這段:
.withChoice()
.source(ComplexFormStates.CHECK_CHOICE) .first(ComplexFormStates.CONFIRM_FORM, new ComplexFormCheckChoiceGuard(),new ComplexFormChoiceAction()) .last(ComplexFormStates.DEAL_FORM,new ComplexFormChoiceAction()) .and()
這是builder里面的代碼片段,我們直接把a(bǔ)ction插入進(jìn)來(lái),在狀態(tài)變化的時(shí)候就能在action里面處理了,下面是這個(gè)action
的代碼:
public class ComplexFormChoiceAction implements Action
@Override public void execute(StateContextcontext) { System.out.println("into ComplexFormChoiceAction"); Form form = context.getMessage().getHeaders().get("form", Form.class); System.out.println(form); System.out.println(context.getStateMachine().getState()); }
}
這里面只有一個(gè)execute的方法,簡(jiǎn)單明了,我們需要的參數(shù)通過(guò)context傳遞,其實(shí)還是message,這樣的話,不同業(yè)務(wù)用不同的action就行了,我們?cè)倩仡^看builder里面插入action的地方:
.first(ComplexFormStates.CONFIRM_FORM, new ComplexFormCheckChoiceGuard(),new ComplexFormChoiceAction(),new ComplexFormChoiceAction())
action可以多個(gè)插入,也就是有多少多帶帶的業(yè)務(wù)需要在這里面處理都行,其實(shí)回過(guò)頭來(lái),不止在withChoice()里面可以,之前的withExternal()也是可以的,看代碼:
.withExternal()
.source(ComplexFormStates.FULL_FORM).target(ComplexFormStates.CHECK_CHOICE) .event(ComplexFormEvents.CHECK) .action(new ComplexFormChoiceAction(),new ComplexFormChoiceAction()) .guard(new ComplexFormCheckChoiceGuard()) .and()
action可以插入多個(gè),但guard在這里恢復(fù)了本來(lái)的作用,保護(hù)狀態(tài)變化,所以只能插入一個(gè)。
3、在controller里面看結(jié)果
最后,我們還是需要看下運(yùn)行的結(jié)果,我準(zhǔn)備了三個(gè)流程:
check成功,成為SUCCESS_FORM
check失敗,deal成功,回到FULL_FORM
check失敗,deal失敗,成為FAILED_FORM
對(duì)應(yīng)的是form1,form2和form3,看代碼:
@Autowired
private ComplexFormStateMachineBuilder complexFormStateMachineBuilder;
......
@RequestMapping("/testComplexFormState")
public void testComplexFormState() throws Exception { StateMachinestateMachine = 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); // 創(chuàng)建流程 System.out.println("-------------------form1------------------"); stateMachine.start(); Message message = MessageBuilder.withPayload(ComplexFormEvents.WRITE).setHeader("form", form1).build(); stateMachine.sendEvent(message); System.out.println("當(dāng)前狀態(tài):" + stateMachine.getState().getId()); message = MessageBuilder.withPayload(ComplexFormEvents.CHECK).setHeader("form", form1).build(); stateMachine.sendEvent(message); System.out.println("當(dāng)前狀態(tài):" + stateMachine.getState().getId()); message = MessageBuilder.withPayload(ComplexFormEvents.DEAL).setHeader("form", form1).build(); stateMachine.sendEvent(message); System.out.println("當(dāng)前狀態(tài):" + stateMachine.getState().getId()); message = MessageBuilder.withPayload(ComplexFormEvents.SUBMIT).setHeader("form", form1).build(); stateMachine.sendEvent(message); System.out.println("最終狀態(tài):" + 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("當(dāng)前狀態(tài):" + stateMachine.getState().getId()); message = MessageBuilder.withPayload(ComplexFormEvents.CHECK).setHeader("form", form2).build(); stateMachine.sendEvent(message); System.out.println("當(dāng)前狀態(tài):" + stateMachine.getState().getId()); message = MessageBuilder.withPayload(ComplexFormEvents.DEAL).setHeader("form", form2).build(); stateMachine.sendEvent(message); System.out.println("當(dāng)前狀態(tài):" + stateMachine.getState().getId()); message = MessageBuilder.withPayload(ComplexFormEvents.SUBMIT).setHeader("form", form2).build(); stateMachine.sendEvent(message); System.out.println("最終狀態(tài):" + 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("當(dāng)前狀態(tài):" + stateMachine.getState().getId()); message = MessageBuilder.withPayload(ComplexFormEvents.CHECK).setHeader("form", form3).build(); stateMachine.sendEvent(message); System.out.println("當(dāng)前狀態(tài):" + stateMachine.getState().getId()); form3.setFormName("好的表單"); message = MessageBuilder.withPayload(ComplexFormEvents.DEAL).setHeader("form", form3).build(); stateMachine.sendEvent(message); System.out.println("當(dāng)前狀態(tài):" + 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("當(dāng)前狀態(tài):" + stateMachine.getState().getId()); message = MessageBuilder.withPayload(ComplexFormEvents.SUBMIT).setHeader("form", form3).build(); stateMachine.sendEvent(message); System.out.println("最終狀態(tài):" + stateMachine.getState().getId()); }
......
看console的結(jié)果就知道正確與否
構(gòu)建復(fù)雜表單狀態(tài)機(jī)
complexFormMachine
-------------------form1------------------
2019-05-13 18:07:19.364 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---空白復(fù)雜表單---
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
傳遞的參數(shù):Form [id=111, formName=null]
2019-05-13 18:07:19.381 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---填寫完復(fù)雜表單---
當(dāng)前狀態(tài):FULL_FORM
傳遞的參數(shù):Form [id=111, formName=null]
2019-05-13 18:07:19.386 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---校驗(yàn)復(fù)雜表單---
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]]
當(dāng)前狀態(tài):DEAL_FORM
傳遞的參數(shù):Form [id=111, formName=null]
2019-05-13 18:07:19.389 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---處理復(fù)雜表單---
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]]
當(dāng)前狀態(tài):FAILED_FORM
最終狀態(tài):FAILED_FORM
-------------------form2------------------
構(gòu)建復(fù)雜表單狀態(tài)機(jī)
2019-05-13 18:07:19.394 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---空白復(fù)雜表單---
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
傳遞的參數(shù):Form [id=222, formName=好的表單]
2019-05-13 18:07:19.395 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---填寫完復(fù)雜表單---
當(dāng)前狀態(tài):FULL_FORM
傳遞的參數(shù):Form [id=222, formName=好的表單]
2019-05-13 18:07:19.396 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---校驗(yàn)復(fù)雜表單---
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]]
當(dāng)前狀態(tài):CONFIRM_FORM
當(dāng)前狀態(tài):CONFIRM_FORM
傳遞的參數(shù):Form [id=222, formName=好的表單]
2019-05-13 18:07:19.399 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---表單提交成功---
最終狀態(tài):SUCCESS_FORM
-------------------form3------------------
構(gòu)建復(fù)雜表單狀態(tài)機(jī)
2019-05-13 18:07:19.404 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---空白復(fù)雜表單---
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
傳遞的參數(shù):Form [id=333, formName=null]
2019-05-13 18:07:19.409 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---填寫完復(fù)雜表單---
當(dāng)前狀態(tài):FULL_FORM
傳遞的參數(shù):Form [id=333, formName=null]
2019-05-13 18:07:19.410 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---校驗(yàn)復(fù)雜表單---
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]]
當(dāng)前狀態(tài):DEAL_FORM
傳遞的參數(shù):Form [id=333, formName=好的表單]
2019-05-13 18:07:19.412 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---處理復(fù)雜表單---
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]]
當(dāng)前狀態(tài):FULL_FORM
傳遞的參數(shù):Form [id=333, formName=好的表單]
2019-05-13 18:07:19.413 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---校驗(yàn)復(fù)雜表單---
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]]
當(dāng)前狀態(tài):CONFIRM_FORM
傳遞的參數(shù):Form [id=333, formName=好的表單]
2019-05-13 18:07:19.415 INFO 6188 --- [nio-9991-exec-1] tConfig$$EnhancerBySpringCGLIB$$37df7571 : ---表單提交成功---
最終狀態(tài):SUCCESS_FORM
大家可以跑一下,對(duì)照狀態(tài)機(jī)的流程圖,看下結(jié)果。
4、繼續(xù)廢話
其實(shí)spring statemachine寫到這里,基本上已經(jīng)可以上手去做企業(yè)開發(fā)了。當(dāng)然,spring statemachine里面還有很多其他的東西,大部分是處理復(fù)雜狀態(tài)機(jī)流程的,以后有機(jī)會(huì)我們?cè)僬归_講。
源代碼地址
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/75298.html
摘要:在實(shí)際的企業(yè)開發(fā)中,不可能所有情況都是從頭到尾的按狀態(tài)流程來(lái),會(huì)有很多意外,比如歷史數(shù)據(jù),故障重啟后的遺留流程,所以這種可以任意調(diào)節(jié)狀態(tài)的才是我們需要的狀態(tài)機(jī)。 1、偽持久化和中間段的狀態(tài)機(jī)我們?cè)O(shè)想一個(gè)業(yè)務(wù)場(chǎng)景,就比如訂單吧,我們一般的設(shè)計(jì)都會(huì)把訂單狀態(tài)存到訂單表里面,其他的業(yè)務(wù)信息也都有表保存,而狀態(tài)機(jī)的主要作用其實(shí)是規(guī)范整個(gè)訂單業(yè)務(wù)流程的狀態(tài)和事件,所以狀態(tài)機(jī)要不要保存真的不重要,...
摘要:讓我們先看下?tīng)顟B(tài)機(jī)的概念。下面是狀態(tài)機(jī)模型中的個(gè)要素,即現(xiàn)態(tài)條件動(dòng)作次態(tài)。因?yàn)橛唵魏蛯徟亩加泻芏嗟牧鞒?,每個(gè)流程都會(huì)產(chǎn)生狀態(tài)的變化,而且流程是這種業(yè)務(wù)的主軸,其他都是圍繞這個(gè)流程和狀態(tài)變化來(lái)考慮的,所以看起來(lái)蠻適合用狀態(tài)機(jī)來(lái)做。 1、背景在我打算學(xué)習(xí)spring statemachine的時(shí)候,我?guī)缀蹩催^(guò)了所有網(wǎng)上的中文教程,基本上都處于淺嘗輒止的階段,有幾篇講的比較深入的,都只是...
摘要:雖然多個(gè)狀態(tài)機(jī)的問(wèn)題解決了,但是對(duì)于實(shí)際的企業(yè)應(yīng)用而言,還是有問(wèn)題。這個(gè)問(wèn)題就用到了狀態(tài)機(jī)的持久化,我們下一章就談?wù)劤志没瘑?wèn)題。 1、多個(gè)狀態(tài)機(jī)的搞法在實(shí)際的企業(yè)應(yīng)用中,基本不可能只有一個(gè)狀態(tài)機(jī)流程在跑,比如訂單,肯定是很多個(gè)訂單在運(yùn)行,每個(gè)訂單都有自己的訂單狀態(tài)機(jī)流程,但上一章的例子,大家可以試一下,當(dāng)執(zhí)行到一個(gè)狀態(tài)時(shí),再次刷新頁(yè)面,不會(huì)有任何日志出現(xiàn),當(dāng)一個(gè)狀態(tài)流程執(zhí)行到某個(gè)狀態(tài),...
摘要:先來(lái)一個(gè),它的主要作用就告訴狀態(tài)機(jī)的初始狀態(tài)應(yīng)該啥樣,然后把整個(gè)狀態(tài)流程都用代碼配置出來(lái)。繼承了類,表明身份,我就是來(lái)配置狀態(tài)機(jī)的初始狀態(tài),并描繪一下?tīng)顟B(tài)流程的全過(guò)程。 上一篇說(shuō)了很多廢話,這一篇就不嘮叨,先跑起來(lái) 1、來(lái)個(gè)spring boot去start.spring.io新建一個(gè)springboot的項(xiàng)目,雖然我對(duì)spirngboot也有不少的牢騷,但作為demo的開始,還是一個(gè)...
摘要:目前為止,多個(gè)狀態(tài)機(jī)和多種狀態(tài)機(jī)都可以在里面實(shí)現(xiàn)了,下一章我們來(lái)解決下?tīng)顟B(tài)機(jī)和實(shí)際業(yè)務(wù)間的數(shù)據(jù)傳輸問(wèn)題,畢竟我們不是為了讓狀態(tài)機(jī)自個(gè)獨(dú)自玩耍,和業(yè)務(wù)數(shù)據(jù)互通有無(wú)才是企業(yè)開發(fā)的正道。 在上一章的例子中,我們實(shí)現(xiàn)了多個(gè)狀態(tài)機(jī)并存執(zhí)行,不同的訂單有各自的狀態(tài)機(jī)運(yùn)行,但只有一種狀態(tài)機(jī),這顯然不能滿足實(shí)際業(yè)務(wù)的要求,比如我就遇到了訂單流程和公文審批流程在同一個(gè)項(xiàng)目的情況,所以我們這一章講怎么讓多...
閱讀 2743·2023-04-25 14:21
閱讀 1180·2021-11-23 09:51
閱讀 4025·2021-09-22 15:43
閱讀 613·2019-08-30 15:55
閱讀 1564·2019-08-29 11:28
閱讀 2450·2019-08-26 11:44
閱讀 1686·2019-08-23 18:15
閱讀 2886·2019-08-23 16:42