在企业开发中,数据在不一样的业务间传输是最多见的工做,因此虽然咱们的主架构是用的状态机,也就是从流程状态的角度来看待这个项目,但在具体业务中,每一个状态的转变中会牵涉到各种业务,这些业务有些须要收到状态机变化的通知,须要把状态值传递给业务类和业务方法,一样的,在处理状态变化是,也须要获取业务数据,方便不一样的业务在同一个状态变化环节作各自的业务,下面咱们就讲下这个数据在spring statemachine里面的传递。spring
此次咱们的顺序变一下,由外部传入一个订单号到controller开始:数据库
@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数据对象,这里为了简化代码,就新建一个啦。app
而后就是真正的主角登场了,Message。它其实不是spirng statemachine专属的,它是spring里面通用的一种消息工具,看它的源代码:工具
package org.springframework.messaging;ui
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();
}
它由两个部分组成,看图就知道了,和代码里面是一致的code
在spring statemachine里面,咱们把状态塞到message的payload里面,而后把须要传递的业务数据(例子里面就是order对象)塞到header里面。建立message用的是messagebuilder,看它的名字就知道是专门建立message的。对象
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方法的参数由以前的为空:
public void receive() {
logger.info("---用户已收货,订单完成---");
}
改为了Message<OrderEvents> message,这样就能从message的getHeaders里面取到传递过来的数据对象了。
另外若是咱们须要传递多个数据对象怎么办呢,好比咱们在实际业务中,除了传订单数据,可能还须要把商品数据,或者支付结果数据也传过来,那么也容易,咱们仍是从controller里面开始:
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对象就和其余的业务代码作到了数据链接。其实这个很关键,只有作到和其余业务的数据传递,才能算的上真正的可用。
下一章咱们继续讲状态机的持久化问题和怎么在非起始状态开始建立状态机
码云配套代码地址