除了上面文章裏面提到的一根筋狀態機流程,實際的企業應用中狀態機的流程會更加複雜,而咱們最經常使用到的就是choice。它相似於java的if語句,做爲條件判斷的分支而存在,讓咱們先看一張圖:java
這張圖表現的是一個表單(form)的整個狀態流程:git
你們不要在乎這個例子的幼稚,畢竟它仍是能用簡單的方式體現出流程的複雜性(這話多麼的辯證統一)。它有判斷分支(還有兩個),還有流程的循環,還有分支判斷後的直接失敗和分支判斷後的後續環節,後面咱們會在代碼中告訴你們這裏面須要注意的東西。spring
先上狀態機的四件套:States,Events,Builder和EventConfig(spring statemachine仍是蠻簡單的,來來回回就這幾樣東西)app
public enum ComplexFormStates { BLANK_FORM, // 空白表單 FULL_FORM, // 填寫完表單 CHECK_CHOICE,//表單校驗判斷 DEAL_CHOICE,//表單處理校驗 DEAL_FORM,//待處理表單 CONFIRM_FORM, // 校驗完表單 SUCCESS_FORM,// 成功表單 FAILED_FORM//失敗表單 }
注意一點,choice判斷分支自己也是一種狀態,要聲明出來,這裏是CHECK_CHOICE和DEAL_CHOICEide
public enum ComplexFormEvents { WRITE, // 填寫 CHECK,//校驗 DEAL,//處理 SUBMIT // 提交 }
一樣的分支事件也要聲明,這裏是CHECK和DEAL。ui
大頭是MachineBuilder,這個代碼就比較多,你們最好對照着上面這張圖來看,會比較清晰lua
/** * 複雜訂單狀態機構建器 */ @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(); } }
這裏面出現了幾個新東西,要說一下:spa
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代碼是這樣的code
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:orm
@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成功後須要通知後續人員來處理什麼的,這該怎麼辦呢?
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在這裏恢復了原本的做用,保護狀態變化,因此只能插入一個。
最後,咱們仍是須要看下運行的結果,我準備了三個流程:
對應的是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
你們能夠跑一下,對照狀態機的流程圖,看下結果。
其實spring statemachine寫到這裏,基本上已經能夠上手去作企業開發了。固然,spring statemachine裏面還有不少其餘的東西,大部分是處理複雜狀態機流程的,之後有機會咱們再展開講。