一個簡單的squirrel-foundation-demo
利用狀態機模擬一個訂單的支付過程。
squirrel-foundation沒有任何嚴重的依賴關系,因此基本上它應該是高度可嵌入的。squirrel-foundation沒有整合spring框架,所以首先要用spring集成squirrel-foundation。
spring集成squirrel-foundation
(1).通過Spring創建StateMachineBuilder實例(單例);
(2).業務函數中通過(1)的StateMachineBuilder實例創建StateMachine實例,并向StateMachine暴露SpringApplicationContext,以便于StateMachine通過ApplicationContext獲取數據層的對象。
public class AbstractStateMachineEngine <T extends UntypedStateMachine> implements ApplicationContextAware {private ApplicationContext applicationContext;protected UntypedStateMachineBuilder stateMachineBuilder = null;@SuppressWarnings("unchecked")public AbstractStateMachineEngine() {//識別泛型參數Class<T> genericType = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(),AbstractStateMachineEngine.class);stateMachineBuilder = StateMachineBuilderFactory.create(genericType, ApplicationContext.class);}//注入applicationContext,并在創建StateMachine實例時注入@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public void fire(OrderEvent event, OrderContext context) {T stateMachine = stateMachineBuilder.newUntypedStateMachine(context.orderDTO.getState(),//暫時開啟debug進行日志traceStateMachineConfiguration.create().enableDebugMode(true).enableAutoStart(true),//注入applicationContextapplicationContext);stateMachine.fire(event, context);}
}
- ?
繼承AbstractStateMachineEngine,并加入@Service注解,便可以在項目中注入。(單例)
@Service
public class OrderStateMachineEngine extends AbstractStateMachineEngine<SubmitOrderStateMachine>{}
- ?
基于注解的方式定義狀態機
@States 定義狀態列表,里面可以包含多個狀態
@State定義每個狀態,name狀態名稱,entryStateInit進入狀態時調用的方法,exitCallMethod 離開狀態是調用的方法,initialState 為true時,為默認狀態。
@States({@State(name = "INIT", entryCallMethod = "entryStateInit", exitCallMethod = "exitStateInit", initialState = true),@State(name = "WAIT_PAY", entryCallMethod = "entryStateWaitPay", exitCallMethod = "exitStateWaitPay"),@State(name = "WAIT_SEND", entryCallMethod = "entryStateWaitSend", exitCallMethod = "exitStateWaitSend"),@State(name = "PART_SEND", entryCallMethod = "entryStatePartSend", exitCallMethod = "exitStatePartSend"),@State(name = "WAIT_RECEIVE", entryCallMethod = "entryStateWaitReceive", exitCallMethod = "exitStateWaitReceive"),@State(name = "COMPLETE", entryCallMethod = "entryStateComplete", exitCallMethod = "exitStateComplete")
})
@Transitions({@Transit(from = "INIT", to = "WAIT_PAY", on = "SUBMIT_ORDER", callMethod = "submitOrder"),@Transit(from = "WAIT_PAY", to = "WAIT_SEND", on = "PAY", callMethod = "pay"),@Transit(from = "WAIT_SEND", to = "PART_SEND", on = "PART_SEND", callMethod = "partSend"),@Transit(from = "PART_SEND", to = "WAIT_RECEIVE", on = "SEND", callMethod = "send"),@Transit(from = "WAIT_RECEIVE", to = "COMPLETE", on = "COMPLETE", callMethod = "complete")
})
@StateMachineParameters(stateType = OrderState.class, eventType = OrderEvent.class, contextType = OrderContext.class)
public class SubmitOrderStateMachine extends AbstractStateMachine<UntypedStateMachine, Object, Object, Object> implements UntypedStateMachine {private OrderService orderService;protected ApplicationContext applicationContext;//定義構造函數接受ApplicationContext注入([參看New State Machine Instance](http://hekailiang.github.io/squirrel/))public SubmitOrderStateMachine(ApplicationContext applicationContext) {this.applicationContext = applicationContext;// 通過applicationContext注入orderServiceorderService = (OrderService) this.applicationContext.getBean(OrderService.class);}public void submitOrder(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {orderService.submitOrder(toState);}public void pay(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("pay");}public void partSend(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("partSend");}public void send(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("send");}public void complete(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("complete");}public void entryStateInit(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("entryStateInit");}public void exitStateInit(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("exitStateInit");}public void entryStateWaitPay(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("entryStateWaitPay");}public void exitStateWaitPay(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("exitStateWaitPay");}public void entryStateWaitSend(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("entryStateWaitSend");}public void exitStateWaitSend(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("exitStateWaitSend");}public void entryStatePartSend(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("entryStatePartSend");}public void exitStatePartSend(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("exitStatePartSend");}public void entryStateWaitReceive(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("entryStateWaitReceive");}public void exitStateWaitReceive(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("exitStateWaitReceive");}public void entryStateComplete(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("entryStateComplete");}public void exitStateComplete(OrderState fromState, OrderState toState, OrderEvent orderEvent, OrderContext orderContext) {System.out.println("exitStateComplete");}}
- ?
Service的實現,更新訂單狀態
@Service
public class OrderService {@AutowiredOrderDTOMapper orderDTOMapper;public int submitOrder(OrderState state) {OrderDTO orderDTO = new OrderDTO();orderDTO.setState(state);orderDTOMapper.insert(orderDTO);return 1;}}
- ?
mapper
@Mapper
public interface OrderDTOMapper {int insert(OrderDTO orderDTO);}
- ?
Controller類測試
注入OrderStateMachineEngine ,初始化狀態為INIT,通過OrderStateMachineEngine 觸發SUBMIT_ORDER事件,發生狀態變化,并將轉換后的狀態插入數據庫。
@RestController
@RequestMapping(value = "/order/")
public class OrderController {// 注入狀態機@AutowiredOrderStateMachineEngine orderStateMachineEngine;@RequestMapping("/test")public void test(){OrderDTO orderDTO = new OrderDTO(OrderState.INIT);OrderContext orderContext = new OrderContext(orderDTO);orderStateMachineEngine.fire(OrderEvent.SUBMIT_ORDER,orderContext);}}
- ?
以下是所用到的實體類定義和狀態及事件
訂單的實體
public class OrderDTO {private Integer id;private OrderState state;private Date createTime;private Date updateTime;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public OrderState getState() {return state;}public void setState(OrderState state) {this.state = state;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}public Date getUpdateTime() {return updateTime;}public void setUpdateTime(Date updateTime) {this.updateTime = updateTime;}@Overridepublic String toString() {return "OrderDTO{" +"id=" + id +", state='" + state + '\'' +", createTime=" + createTime +", updateTime=" + updateTime +'}';}public OrderDTO(OrderState state) {this.state = state;}public OrderDTO() {}
}
- ?
定義訂單的狀態
public enum OrderState {INIT,WAIT_PAY,WAIT_SEND,PART_SEND,WAIT_RECEIVE,COMPLETE,CANCELED;public static OrderState getState(String state) {for (OrderState orderState : OrderState.values()) {if (orderState.name().equalsIgnoreCase(state)) {return orderState;}}return null;}
}
- ?
定義訂單的事件
public enum OrderEvent {SUBMIT_ORDER,PAY,PART_SEND,SEND,COMPLETE}
- ?
定義上下文
public class OrderContext {public OrderContext(OrderDTO orderDTO) {this.orderDTO = orderDTO;}public OrderContext() {}public OrderDTO orderDTO;}