squirrel-foundation的一些使用方法在百度上资料还是比较少,我是根据以下三个大佬写的文章借鉴的,在这里记录一下。
1、squirrel-foundation-demo
2、Squirrel使用(中文文档)
3、squirrel-foundation状态机的使用细节
我在这里直接粘贴代码,便于自己之后理解。
/**
* 通过Spring创建StateMachineBuilder实例,通过buidler创建状态机(单例)
* 创建无类型化状态机,简化状态机,防止过多泛化导致代码不易阅读(因为不太理解一些高级的使用)
*/
public abstract 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实例时注入
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 可以通过向OrderContext 上下文传递一些业务参数,比如orderId等等
*/
public boolean fire(EOrderEvents event, OrderContext context) {
T stateMachine = stateMachineBuilder.newUntypedStateMachine(
context.geteOrder().getOrderStatus(),
applicationContext);
//由于StateMachine实例不是由Spring容器创建,所以这个过程中无法通过注解方式开启事务(Spring没有机会去创建事务代理),因此采用了编程式事务
DataSourceTransactionManager transactionManager = (DataSourceTransactionManager)applicationContext.getBean("transactionManager");
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = transactionManager.getTransaction(def);
try {
stateMachine.fire(event, context);
transactionManager.commit(status);
//这里会返回状态机是否出错,如果出错可用于通知Controller层,目前只会这样简单的操作
return stateMachine.isError();
} catch (Exception ex) {
//用于事务回滚
transactionManager.rollback(status);
return true;
}
}
}
/**
* 该类相当于监听状态变化,构造一些监听方法实现一些逻辑代码
* @States 定义状态列表,里面可以包含多个状态
* @State定义每个状态,name状态名称,entryStateInit进入状态时调用的方法,exitCallMethod 离开状态是调用的方法,initialState 为true时,为默认状态。
* */
@States({
@State(name = "UNFOUND", entryCallMethod = "entryStateInit", exitCallMethod = "exitStateInit", initialState = true),
@State(name = "USING", entryCallMethod = "entryStateWaitPay", exitCallMethod = "exitStateWaitPay"),
@State(name = "COMPLETE", entryCallMethod = "entryStateWaitSend", exitCallMethod = "exitStateWaitSend"),
@State(name = "REFUND", entryCallMethod = "entryStatePartSend", exitCallMethod = "exitStatePartSend"),
@State(name = "NOUSE", entryCallMethod = "entryStatePartSend", exitCallMethod = "exitStatePartSend")
})
@Transitions({
@Transit(from = "UNFOUND", to = "UNFOUND", on = "FOUND", callMethod = "createOrder"),
@Transit(from = "UNFOUND", to = "USING", on = "SAOMA", callMethod = "submitOrder"),
@Transit(from = "USING", to = "COMPLETE", on = "PAY", callMethod = "pay"),
@Transit(from = "USING", to = "REFUND", on = "USING_REFUNDING", callMethod = "usingRefund"),
@Transit(from = "COMPLETE", to = "REFUND", on = "COM_REFUNDING", callMethod = "comRefund")
})
//该地方向AbstractStateMachine传递的参数
@StateMachineParameters(stateType = OrderStates.class, eventType = OrderEvents.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注入orderService,这样就可以通过service操作数据库
OrderService = (OrderService) this.applicationContext.getBean("OrderService");
}
//创建订单,依旧处于待使用状态
public void createOrder(OrderStates fromState, OrderStates toState, OrderEvents OrderEvents, OrderContext OrderContext) {
//可以做一些创建订单等等操作
}
//提交订单
public void submitOrder(OrderStates fromState, OrderStates toState, OrderEvents OrderEvents, OrderContext OrderContext) {
}
//支付订单
public void pay(OrderStates fromState, OrderStates toState, OrderEvents OrderEvents, OrderContext OrderContext) {
}
public void usingRefund(OrderStates fromState, OrderStates toState, OrderEvents OrderEvents, OrderContext OrderContext) {
}
public void comRefund(OrderStates fromState, OrderStates toState, OrderEvents OrderEvents, OrderContext OrderContext) {
}
/**
* 如果实现这个方法,当上面方法执行出现错误时就会转到这里来执行。
* 但是由于自己是菜鸟,并不知道出错后这里该如何通知到Controller层
* 因此这里并未实现,具体的实现方法请参考官网
*/
/*
@Override
protected void afterTransitionCausedException(Object fromState, Object toState, Object event, Object context) {
//super.afterTransitionCausedException(fromState, toState, event, context);
}*/
}
还需要一个类集成AbstractStateMachineEngine,用于调用fire()方法。该类需要添加@Service注解,以便spring注入
@Service
public class OrderStateMachineEngine extends AbstractStateMachineEngine<SubmitOrderStateMachine>{
}
Controller层使用:
/**
* 这里需要加上try**catch**,以便发生错误可方便执行下去
*/
@RequestMapping(value="/modOrderStatus",method = {RequestMethod.POST})
@ResponseBody
public ResultEntity<Order> modOrderStatus(@RequestParam("event") String event,int code,Long orderId){
ResultEntity<Order> resultEntity = new ResultEntity<Order>();
try {
Order Order = new Order();
Order.setOrderStatus(OrderStates.getState(code));
//向订单上下文可添加一些逻辑参数,如:orderId
OrderContext OrderContext = new OrderContext(Order, orderId);
if(!orderStateMachineEngine.fire(OrderEvents.getEvent(event), OrderContext)) {
resultEntity.setCode(1);
resultEntity.setMessage("成功!");
}else {
resultEntity.setCode(0);
resultEntity.setMessage("更新失败,请重新尝试!");
}
return resultEntity;
} catch (Exception e) {
e.printStackTrace();
log.error(e);
resultEntity.setCode(0);
resultEntity.setMessage("更新失败,请重新尝试!");
return resultEntity;
}
}
OrderContext类:
/**
* 订单上下文
* */
public class OrderContext {
public OrderContext(Order eOrder,Long orderId) {
this.Order = Order;
this.orderId = orderId;
}
public OrderContext() {
}
private Order Order;
//逻辑参数
private Long orderId;
public Order getOrder() {
return Order;
}
public void seteOrder(Order Order) {
this.Order = Order;
}
public Long getOrderId() {
return orderId;
}
public void setOrderId(Long orderId) {
this.orderId = orderId;
}
}
OrderEvents枚举:
/**
* 订单状态转变事件
* */
public enum OrderEvents {
FOUND, //创建订单
SAOMA, //提交订单
PAY, //付款
USING_REFUNDING,
COM_REFUNDING;
public static OrderEvents getEvent(String event) {
for (OrderEvents orderEvent : OrderEvents.values()) {
if (orderEvent.name().equals(event)) {
return orderEvent;
}
}
return null;
}
}
OrderStatus枚举:
/**
* 订单状态
* */
public enum OrderStates implements IEnum<Integer>{
UNFOUND(1,"待使用"),
USING(2,"正使用"),
COMPLETE(3,"已完成"),
REFUND(4,"退款"),
NOUSE(5,"放弃订单");
private String desc;
private int code;
private OrderStates(int code,String desc) {
this.code = code;
this.desc = desc;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public static OrderStates getState(int code) {
for (OrderStates orderState : OrderStates.values()) {
if (orderState.ordinal()+1 == code) {
return orderState;
}
}
return null;
}
/**
* 实现IEnum接口重写的该方法
* 该方法的作用就是表示返回的值,将要存储在数据库中
* 和EnumValue注解作用一样,在字段上EnumValue,就可不需要实现IEnum接口
* */
@Override
public Integer getValue() {
// TODO Auto-generated method stub
return code;
}