株洲网站关键词优化,上海网站建设推荐q479185700顶你,丹东淘宝做网站,wordpress数据说起Spring状态机#xff0c;大家很容易联想到这个状态机和设计模式中状态模式的区别是啥呢#xff1f;没错#xff0c;Spring状态机就是状态模式的一种实现#xff0c;在介绍Spring状态机之前#xff0c;让我们来看看设计模式中的状态模式。 1. 状态模式 状态模式的定义如…说起Spring状态机大家很容易联想到这个状态机和设计模式中状态模式的区别是啥呢没错Spring状态机就是状态模式的一种实现在介绍Spring状态机之前让我们来看看设计模式中的状态模式。 1. 状态模式 状态模式的定义如下 状态模式State Pattern是一种行为型设计模式它允许对象在内部状态发生变化时改变其行为。在状态模式中一个对象的行为取决于其当前状态而且可以随时改变这个状态。状态模式将对象的状态封装在不同的状态类中从而使代码更加清晰和易于维护。当一个对象的状态改变时状态模式会自动更新该对象的行为而不需要在代码中手动进行判断和处理。 通常业务系统中会存在一些拥有状态的对象而且这些状态之间可以进行转换并且在不同的状态下会表现出不同的行为或者不同的功能比如交通灯控制系统中会存在红灯、绿灯和黄灯再比如订单系统中的订单会存在已下单、待支付、待发货、待收货等状态这些状态会通过不同的行为进行相互转换这时候在系统设计时就可以使用状态模式。 下面是状态模式的类图 可以看到状态模式主要包含三种类型的角色 1、上下文(**Context**)角色封装了状态的实例负责维护状态实例并将请求委托给当前的状态对象。 2、抽象状态(**State**)角色定义了表示不同状态的接口并封装了该状态下的行为。所有具体状态都实现这个接口。 3、具体状态(**Concrete State**)角色具体实现了抽象状态角色的接口并封装了该状态下的行为。 下面是使用状态模式实现红绿灯状态变更的一个简单案例 抽象状态类 /*** description: 抽象状态类*/
public abstract class MyState {abstract void handler();
} 具体状态类A /*** description: 具体状态A*/
public class RedLightState extends MyState{Overridevoid handler() {System.out.println(红灯停);}
} 具体状态类B /*** description: 具体状态B*/
public class GreenLightState extends MyState{Overridevoid handler() {System.out.println(绿灯行);}
} 环境类维护当前状态对象并提供了切换状态的方法。 /*** description: 环境类*/
public class MyContext {private MyState state;public void setState(MyState state) {this.state state;}public void handler() {state.handler();}
} 测试类 /*** description: 测试状态模式*/
public class TestStateModel {public static void main(String[] args) {MyContext myContext new MyContext();RedLightState redLightState new RedLightState();GreenLightState greenLightState new GreenLightState();myContext.setState(redLightState);myContext.handler(); //红灯停myContext.setState(greenLightState);myContext.handler(); //绿灯行}
} 下面是对应的执行结果 可以发现使用状态模式中的状态类在一定程度上也消除了if-else逻辑校验看到这里 有些人可能会有疑问状态模式和策略模式的区别是什么呢 状态模式更关注对象在不同状态的行为和状态之间的流转而策略模式更关注对象不同策略的选择。 上面我们介绍了设计模式中的状态模式接下来我们来看看Spring状态机。 2. Spring状态机 状态机也就是 State Machine 不是指一台实际机器而是指一个数学模型 。说白了就是指一张状态转换图。 状态机是状态模式的一种应用相当于上下文角色的一个升级版。在工作流或游戏等各种系统中有大量使用如各种工作流引擎它几乎是状态机的子集和实现封装状态的变化规则。Spring也提供了一个很好的解决方案。Spring中的组件名称就叫作状态机StateMachine。状态机帮助开发者简化状态控制的开发过程让状态机结构更加层次化。 通过定义我们很容易分析得到状态机应当具备一下几个要素 当前状态也就是状态流转的起始状态。 触发事件引起状态之间流转的一些列动作。 响应函数触发事件到下一个状态之间的规则。 目标状态状态流转的目标状态。 对于组件化的状态机当前使用较多的主要是两种一种是Spring 状态机一种是COLA状态机这两种状态机的对比如下表所示 可以看到Spring状态机锁提供的内容较为丰富当然对于自定义的支持就不如COLA状态机好如果对自定义的需求比较高那建议使用COLA状态机。 本文以Spring状态机为例展示如何在业务系统中使用状态机。 为了便于大家了解Spring状态机的实现原理和使用方式以及其提供的功能下面列出了官方文档和源码感兴趣的同学可以阅读阅读。 官方文档 Spring Statemachine - Reference Documentation 源代码 https://github.com/spring-projects/spring-statemachine 3. Spring状态机实现订单状态流转 对于状态模式Spring封装好了一个组件就叫状态机StateMachine。Spring状态机可以帮助我们开发者简化状态控制的开发过程让状态机结构更加层次化。下面用Spring状态机模拟一个订单状态流转的过程。 3.1 环境准备 首先如果要使用spring状态机需要引入对应的jar包这里我的springboot版本是2.2.1.RELEASE dependencygroupIdorg.springframework.statemachine/groupIdartifactIdspring-statemachine-core/artifactIdversion${springboot.version}/version
/dependency 下面是简化的订单的定义以及订单状态和订单转换行为的枚举 /*** description: 模拟订单类*/
Data
public class Order {private Long orderId;private OrderStatusEnum orderStatus;
}/*** description: 订单状态*/
public enum OrderStatusEnum {// 待支付WAIT_PAYMENT,// 待发货WAIT_DELIVER,// 待收货WAIT_RECEIVE,// 完成FINISH;
}/*** description:订单状态转换行为*/
public enum OrderStatusChangeEventEnum {//支付PAYED,//发货DELIVERY,//收货RECEIVED;
} 3.2 构造订单状态机 在引入jar包之后需要构建一个针对订单状态流转的状态机 订单状态机配置类如下 /*** description: 订单状态机*/
Configuration
EnableStateMachine
public class OrderStatusMachineConfig extends StateMachineConfigurerAdapterOrderStatusEnum, OrderStatusChangeEventEnum {/*** 配置状态*/Overridepublic void configure(StateMachineStateConfigurerOrderStatusEnum, OrderStatusChangeEventEnum states) throws Exception {states.withStates().initial(OrderStatusEnum.WAIT_PAYMENT).end(OrderStatusEnum.FINISH).states(EnumSet.allOf(OrderStatusEnum.class));}/*** 配置状态转换事件关系*/Overridepublic void configure(StateMachineTransitionConfigurerOrderStatusEnum, OrderStatusChangeEventEnum transitions) throws Exception {transitions.withExternal().source(OrderStatusEnum.WAIT_PAYMENT).target(OrderStatusEnum.WAIT_DELIVER).event(OrderStatusChangeEventEnum.PAYED).and().withExternal().source(OrderStatusEnum.WAIT_DELIVER).target(OrderStatusEnum.WAIT_RECEIVE).event(OrderStatusChangeEventEnum.DELIVERY).and().withExternal().source(OrderStatusEnum.WAIT_RECEIVE).target(OrderStatusEnum.FINISH).event(OrderStatusChangeEventEnum.RECEIVED);}
} 3.3 编写状态机监听器 监听状态变更事件完成状态转换。 /*** description: 状态监听*/
Component
WithStateMachine
Transactional
public class OrderStatusListener {OnTransition(source WAIT_PAYMENT, target WAIT_DELIVER)public boolean payTransition(Message message) {Order order (Order) message.getHeaders().get(order);order.setOrderStatus(OrderStatusEnum.WAIT_DELIVER);System.out.println(支付状态机反馈信息 message.getHeaders().toString());return true;}OnTransition(source WAIT_DELIVER, target WAIT_RECEIVE)public boolean deliverTransition(Message message) {Order order (Order) message.getHeaders().get(order);order.setOrderStatus(OrderStatusEnum.WAIT_RECEIVE);System.out.println(发货状态机反馈信息 message.getHeaders().toString());return true;}OnTransition(source WAIT_RECEIVE, target FINISH)public boolean receiveTransition(Message message) {Order order (Order) message.getHeaders().get(order);order.setOrderStatus(OrderStatusEnum.FINISH);System.out.println(收货状态机反馈信息 message.getHeaders().toString());return true;}} 3.4 编写订单服务类 模拟对订单的一些业务操作 /*** description: 订单服务*/
Service
public class OrderServiceImpl implements OrderService {Resourceprivate StateMachineOrderStatusEnum, OrderStatusChangeEventEnum orderStateMachine;private long id 1L;private MapLong, Order orders Maps.newConcurrentMap();Overridepublic Order create() {Order order new Order();order.setOrderStatus(OrderStatusEnum.WAIT_PAYMENT);order.setOrderId(id);orders.put(order.getOrderId(), order);System.out.println(订单创建成功: order.toString());return order;}Overridepublic Order pay(long id) {Order order orders.get(id);System.out.println(尝试支付订单号 id);Message message MessageBuilder.withPayload(OrderStatusChangeEventEnum.PAYED).setHeader(order, order).build();if (!sendEvent(message)) {System.out.println( 支付失败, 状态异常订单号 id);}return orders.get(id);}Overridepublic Order deliver(long id) {Order order orders.get(id);System.out.println( 尝试发货订单号 id);if (!sendEvent(MessageBuilder.withPayload(OrderStatusChangeEventEnum.DELIVERY).setHeader(order, order).build())) {System.out.println( 发货失败状态异常订单号 id);}return orders.get(id);}Overridepublic Order receive(long id) {Order order orders.get(id);System.out.println( 尝试收货订单号 id);if (!sendEvent(MessageBuilder.withPayload(OrderStatusChangeEventEnum.RECEIVED).setHeader(order, order).build())) {System.out.println( 收货失败状态异常订单号 id);}return orders.get(id);}Overridepublic MapLong, Order getOrders() {return orders;}/*** 发送状态转换事件* param message* return*/private synchronized boolean sendEvent(MessageOrderStatusChangeEventEnum message) {boolean result false;try {orderStateMachine.start();result orderStateMachine.sendEvent(message);} catch (Exception e) {e.printStackTrace();} finally {if (Objects.nonNull(message)) {Order order (Order) message.getHeaders().get(order);if (Objects.nonNull(order) Objects.equals(order.getOrderStatus(), OrderStatusEnum.FINISH)) {orderStateMachine.stop();}}}return result;}
} 3.5 测试入口 这里编写一个controller模拟c端用户请求为了便于展示这里使用一个测试方法完成所有的操作 RestController
public class OrderController {Resourceprivate OrderService orderService;RequestMapping(/testOrderStatusChange)public String testOrderStatusChange(){orderService.create();orderService.create();orderService.pay(1L);orderService.deliver(1L);orderService.receive(1L);orderService.pay(2L);orderService.deliver(2L);orderService.receive(2L);System.out.println(全部订单状态 orderService.getOrders());return success;}} 下面是对应的执行结果 可以看到spring状态机很好的控制了订单在各个状态之间的流转。 4. 思考与总结 思考针对状态机的特点还有其他思路实现一个状态机吗下面是一些常规思路如果还有其他方法欢迎在评论区留言。 1. 消息队列方式
订单状态的流转可以通过MQ发布一个事件消费者根据业务条件把订单状态进行流转可以根据不同的事件发送到不同的Topic。 2. 定时任务驱动
每隔一段时间启动一下job根据特定的状态从数据库中拿对应的订单记录然后判断订单是否有条件到达下一个状态。 3. 规则引擎方式
业务团队可以在规则引擎里编写一系列的状态及其对应的转换规则由规则引擎根据已经加载的规则对输入数据进行解析根据解析的结果执行相应的动作完成状态流转。 总结 本文主要介绍了设计模式中的状态模式并在此基础上介绍了Spring状态机相关的概念并根据常见的订单流转场景介绍了Spring状态机的使用方式。文中如有不当之处欢迎在评论区批评指正。 5. 参考内容 Spring Statemachine - Reference Documentation
设计模式-状态模式-腾讯云开发者社区-腾讯云
「聊设计模式」之状态模式State-腾讯云开发者社区-腾讯云
以电商下单场景为例玩一玩有限状态机的流转 - 掘金
状态机的介绍和使用 | 京东物流技术团队 - 京东云开发者的个人空间 - OSCHINA - 中文开源技术交流社区
状态模式之订单状态流转Spring状态机 - 掘金 文章转载自京东云开发者 原文链接https://www.cnblogs.com/Jcloud/p/17915667.html 体验地址引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构