在企業開發中,數據在不一樣的業務間傳輸是最多見的工做,因此雖然咱們的主架構是用的狀態機,也就是從流程狀態的角度來看待這個項目,但在具體業務中,每一個狀態的轉變中會牽涉到各種業務,這些業務有些須要收到狀態機變化的通知,須要把狀態值傳遞給業務類和業務方法,一樣的,在處理狀態變化是,也須要獲取業務數據,方便不一樣的業務在同一個狀態變化環節作各自的業務,下面咱們就講下這個數據在spring statemachine裏面的傳遞。java
此次咱們的順序變一下,由外部傳入一個訂單號到controller開始:git
@RequestMapping("/testOrderState") public void testOrderState(String orderId) throws Exception { StateMachine<OrderStates, OrderEvents> stateMachine = orderStateMachineBuilder.build(beanFactory); System.out.println(stateMachine.getId()); // 建立流程 stateMachine.start(); // 觸發PAY事件 stateMachine.sendEvent(OrderEvents.PAY); // 觸發RECEIVE事件 Order order = new Order(orderId, "547568678", "廣東省深圳市", "13435465465", "RECEIVE"); Message<OrderEvents> message = MessageBuilder.withPayload(OrderEvents.RECEIVE).setHeader("order", order).build(); stateMachine.sendEvent(message); // 獲取最終狀態 System.out.println("最終狀態:" + stateMachine.getState().getId()); }
controller收到request請求的參數,orderId,而後狀態機依次觸發事件,到觸發RECEIVE事件的時候,咱們新建了一個Order,並把orderId塞進去了,其實更多的狀況應該是咱們拿到orderId,而後查詢數據庫,獲得order數據對象,這裏爲了簡化代碼,就新建一個啦。spring
而後就是真正的主角登場了,Message。它其實不是spirng statemachine專屬的,它是spring裏面通用的一種消息工具,看它的源代碼:數據庫
package org.springframework.messaging; public interface Message<T> { /** * Return the message payload. */ T getPayload(); /** * Return message headers for the message (never {@code null} but may be empty). */ MessageHeaders getHeaders(); }
它由兩個部分組成,看圖就知道了,和代碼裏面是一致的架構
在spring statemachine裏面,咱們把狀態塞到message的payload裏面,而後把須要傳遞的業務數據(例子裏面就是order對象)塞到header裏面。建立message用的是messagebuilder,看它的名字就知道是專門建立message的。app
Message<OrderEvents> message = MessageBuilder.withPayload(OrderEvents.RECEIVE).setHeader("order", order).build(); stateMachine.sendEvent(message);
建立了message後,狀態機sendEvent就能夠不僅是傳一個event,能夠組合event(OrderEvents.RECEIVE)和數據內容(order)一塊兒發送給狀態機變化的處理類eventconfig了。讓咱們看eventConfig的處理:工具
/** * WAITING_FOR_RECEIVE->DONE 執行的動做 */ @OnTransition(source = "WAITING_FOR_RECEIVE", target = "DONE") public void receive(Message<OrderEvents> message) { System.out.println("傳遞的參數:" + message.getHeaders().get("order")); logger.info("---用戶已收貨,訂單完成---"); }
首先,receive方法的參數由以前的爲空:ui
public void receive() { logger.info("---用戶已收貨,訂單完成---"); }
改爲了Message<OrderEvents> message,這樣就能從message的getHeaders裏面取到傳遞過來的數據對象了。日誌
另外若是咱們須要傳遞多個數據對象怎麼辦呢,好比咱們在實際業務中,除了傳訂單數據,可能還須要把商品數據,或者支付結果數據也傳過來,那麼也容易,咱們仍是從controller裏面開始:code
Message<OrderEvents> message = MessageBuilder.withPayload(OrderEvents.RECEIVE).setHeader("order", order).setHeader("otherobj", "otherobjvalue").build();
在後面繼續setHeader就行了,而後到eventConfig裏面:
System.out.println("傳遞的參數:" + message.getHeaders().get("order")); System.out.println("傳遞的參數:" + message.getHeaders().get("otherObj"));
運行後看日誌:
傳遞的參數:Order [id=null, userId=547568678, address=廣東省深圳市, phoneNum=13435465465, state=RECEIVE] 傳遞的參數:otherObjValue
可知兩個的數據都傳遞到了eventConfig裏面了,這個就實現了多個數據對象的同時傳遞。
到這裏爲止,狀態機經過message對象就和其餘的業務代碼作到了數據鏈接。其實這個很關鍵,只有作到和其餘業務的數據傳遞,才能算的上真正的可用。
下一章咱們繼續講狀態機的持久化問題和怎麼在非起始狀態開始建立狀態機