一个简单的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;}