当前位置: 首页 > news >正文

深圳门户网站建设中国十大咨询公司

深圳门户网站建设,中国十大咨询公司,郴州网站制作建设,wordpress调用分类产品文章目录 1. 什么是状态2. 有限状态机概述3. Spring StateMachine4. Spring StateMachine 入门小案例4.1 接口测试 5. 总结 1. 什么是状态 在开发中#xff0c;无时无刻离不开状态的一个概念#xff0c;任何一条数据都有属于它的状态。 比如一个电商平台#xff0c;一个订… 文章目录 1. 什么是状态2. 有限状态机概述3. Spring StateMachine4. Spring StateMachine 入门小案例4.1 接口测试 5. 总结 1. 什么是状态 在开发中无时无刻离不开状态的一个概念任何一条数据都有属于它的状态。 比如一个电商平台一个订单会有很多状态比如待付款、待发货、待收货、完成订单。而这其中每一个状态的改变都随着一个个事件的发生。比如将商品下单但未付款那么订单就是待付款状态当触发支付事件那么订单就能从待付款状态转变未待发货状态以此类推随之对应的事件就是发货、收货。 其二状态的流动是固定了的。也就是说待付款状态的下一个状态只能是待发货状态不能直接转化为待收货状态。这种由待付款直接转变未待收货的状态是非法的是程序不允许的。 对于这样的一种情况最简单的解决方案无疑就是if-lese比如编写一个支付接口首先根据订单ID从数据库中查询出来订单信息然后判断一下订单状态是不是待付款状态如果是待付款状态则可以继续下面的流程否则抛出异常告知用户是非法操作。 这种使用硬编码的if-else实现的效果固然没啥问题但是如果中间状态出现了改变比如待付款状态出现一个待拼单那么代码改动幅度未免太大难以维护。 这时候学过设计模式的同学很容易就想到了状态模式。 状态模式将状态改变抽象成了三个角色 环境角色(Context)也称上下文定义了客户端需要的接口维护一个当前状态并将状态的相关操作委托给当前状态对象处理。抽象状态角色(State)定义一个接口用以封装环境对象中的特定状态所对应的行为。具体状态Concrete State角色实现抽象状态所对应的行为。 使用状态模式可以将所有与某个状态有关的行为放到一个类中并且可以方便地增加新的状态只需要改变对象状态即可改变对象的行为。并且允许状态转换逻辑与状态对象合成一体而不是某一个巨大的条件语句块。 但是状态模式也存在缺点 如果一个实物存在过多状态会出现类爆炸问题。状态模式的结构与实现都较为复杂如果使用不当将导致程序结构和代码的混乱。状态模式对开闭原则的支持并不太好对于可以切换状态的状态模式增加新的状态类需要修改那些负责状态转换的源代码否则无法切换到新增状态而且修改某个状态类的行为也需修改对应类的源代码。 对比两种方案状态模式是更好的解决方案而对应到实践也就是状态机。 2. 有限状态机概述 有限状态机Finite-state machine,FSM又称有限状态自动机简称状态机是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。 而要实现状态之间的流转必须具备以下几个要素。 1. 当前状态状态流转的起始状态如上图中的新建状态 2. 触发事件引发状态与状态之间流转的事件如上图中的创建订单这个动作 3. 响应函数触发事件到下一个状态之间的规则 4. 目标状态状态流转的终止状态如上图中的待付款状态 简单来说只有满足当订单是新建状态并且触发创建订单事件才会执行触发函数使得状态由新建转化为待付款。 这就是一个状态机的基本要素但是要实现一个状态机并不简单好在Spring为我们提供了Spring StateMachine框架。 3. Spring StateMachine Spring Statemachine是应用程序开发人员在Spring应用程序中使用状态机概念的框架 Spring Statemachine旨在提供以下功能 易于使用的扁平单级状态机用于简单的使用案例。分层状态机结构以简化复杂的状态配置。状态机区域提供更复杂的状态配置。使用触发器转换警卫和操作。键入安全配置适配器。生成器模式用于在Spring Application上下文之外使用的简单实例化通常用例的食谱基于Zookeeper的分布式状态机状态机事件监听器。UML Eclipse Papyrus建模。将计算机配置存储在永久存储中。Spring IOC集成将bean与状态机关联起来。 官网spring.io/projects/sp… 源码github.com/spring-proj… APIdocs.spring.io/spring-stat… 状态机是一种用于控制应用程序状态转换的机制。它包含了一组预定义的状态和状态之间的转换规则。在应用程序运行时通过不同的事件或计时器触发状态机能够根据事先定义好的规则自动地改变应用程序的状态。这种设计思想使得开发人员能够更加方便地追踪和调试应用程序的行为因为状态转换的规则是在启动时确定的而不需要动态地修改或推断。 4. Spring StateMachine 入门小案例 首先引入Spring StateMachine 的依赖。 dependencygroupIdorg.springframework.statemachine/groupIdartifactIdspring-statemachine-core/artifactIdversion2.1.3.RELEASE/version /dependency定义订单状态的枚举与触发订单状态改变的事件枚举 /*** description: 订单状态* authorlrk* date: 2023/9/6*/ AllArgsConstructor Getter public enum OrderState {WAIT_PAYMENT(1, 待支付),WAIT_DELIVER(2, 待发货),WAIT_RECEIVE(3, 待收货),FINISH(4, 已完成);private Integer value;private String desc; }/*** description: 事件枚举类* authorlrk* date: 2023/9/6*/ public enum OrderStatusChangeEvent {/*** 支付*/PAYED,/*** 发货*/DELIVERY,/*** 确认收货*/RECEIVED }创建一个订单表这里只是简单演示所有只有id、用户名称和订单状态 CREATE TABLE t_order (id bigint NOT NULL AUTO_INCREMENT COMMENT id,name varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 下单用户名称,status tinyint NULL DEFAULT NULL COMMENT 订单状态1待支付2待发货3待收货4已完成,PRIMARY KEY (id) USING BTREE ) ENGINE InnoDB AUTO_INCREMENT 2 CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci ROW_FORMAT Dynamic;SET FOREIGN_KEY_CHECKS 1;接着编写状态机的配置类。 绑定初始状态与解决状态以及所有的订单状态绑定从一个状态流向下一个状态需要触发的事件 /*** description: 状态机配置类* authorlrk* date: 2023/9/6*/ Configuration EnableStateMachine(name orderStateMachine) Slf4j public class OrderStateMachineConfig extends EnumStateMachineConfigurerAdapterOrderState, OrderStatusChangeEvent {/*** 配置初始状态*/Overridepublic void configure(StateMachineStateConfigurerOrderState, OrderStatusChangeEvent states) throws Exception {states.withStates()// 指定初始化状态.initial(OrderState.WAIT_PAYMENT)// 指定解决状态.end(OrderState.FINISH).states(EnumSet.allOf(OrderState.class));}/*** 配置状态转换事件关系** param transitions* throws Exception*/Overridepublic void configure(StateMachineTransitionConfigurerOrderState, OrderStatusChangeEvent transitions) throws Exception {transitions//支付事件:待支付-》待发货.withExternal().source(OrderState.WAIT_PAYMENT).target(OrderState.WAIT_DELIVER).event(OrderStatusChangeEvent.PAYED).and()//发货事件:待发货-》待收货.withExternal().source(OrderState.WAIT_DELIVER).target(OrderState.WAIT_RECEIVE).event(OrderStatusChangeEvent.DELIVERY).and()//收货事件:待收货-》已完成.withExternal().source(OrderState.WAIT_RECEIVE).target(OrderState.FINISH).event(OrderStatusChangeEvent.RECEIVED);} }接着编写状态机监听器。 状态机监听器种指定了状态从某个状态到某个状态的时候会触发哪个方法执行方法的逻辑。 比如订单状态一开始是WAIT_PAYMENT需要转化为WAIT_DELIVER 那么就会执行payTransition方法的逻辑在这个方法中可以编写相应的业务逻辑。 /*** description: 状态机监听器* authorlrk* date: 2023/9/6*/ WithStateMachine(name orderStateMachine) Slf4j Component(orderStateListener) public class OrderListener {Resourceprivate OrderService orderService;OnTransition(source WAIT_PAYMENT, target WAIT_DELIVER)public boolean payTransition(MessageOrderStatusChangeEvent message) {Order order (Order) message.getHeaders().get(order);order.setStatus(OrderState.WAIT_DELIVER.getValue());log.info(支付状态机反馈信息 message.getHeaders().toString());return orderService.updateById(order);}OnTransition(source WAIT_DELIVER, target WAIT_RECEIVE)public boolean deliverTransition(MessageOrderStatusChangeEvent message) {Order order (Order) message.getHeaders().get(order);order.setStatus(OrderState.WAIT_RECEIVE.getValue());log.info(发货状态机反馈信息 message.getHeaders().toString());return orderService.updateById(order);}OnTransition(source WAIT_RECEIVE, target FINISH)public boolean receiveTransition(MessageOrderStatusChangeEvent message) {Order order (Order) message.getHeaders().get(order);order.setStatus(OrderState.FINISH.getValue());log.info(收货状态机反馈信息 message.getHeaders().toString());return orderService.updateById(order);} }接着编写接口 /*** description: 订单接口* authorlrk* date: 2023/9/6*/ RestController RequestMapping(order) public class OrderController {Resourceprivate OrderService orderService;GetMapping(create)public BaseResponseOrder create() {return ResultUtils.success(orderService.create());}GetMapping(pay)public BaseResponseOrder pay(RequestParam Integer id) {return ResultUtils.success(orderService.pay(id));}GetMapping(deliver)public BaseResponseOrder deliver(RequestParam Integer id) {return ResultUtils.success(orderService.deliver(id));}GetMapping(receive)public BaseResponseOrder receive(RequestParam Integer id) {return ResultUtils.success(orderService.receive(id));}GetMapping(getOrders)public BaseResponseListOrder getOrders() {return ResultUtils.success(orderService.getOrders());} }/*** author lrk* description 针对表【t_order】的数据库操作Service实现* createDate 2023-09-06 22:42:22*/ Service Slf4j public class OrderServiceImpl extends ServiceImplOrderMapper, Orderimplements OrderService {Resourceprivate StateMachineOrderState, OrderStatusChangeEvent orderStateMachine;Resourceprivate StateMachinePersisterOrderState, OrderStatusChangeEvent, Order persister;Overridepublic Order create() {Order order new Order();order.setName(小明 UUID.randomUUID());order.setStatus(OrderState.WAIT_PAYMENT.getValue());this.save(order);return order;}Overridepublic Order pay(int id) {Order order this.getById(id);log.info(支付order订单信息{}, order);if (!sendEvent(OrderStatusChangeEvent.PAYED, order)) {throw new BusinessException(ErrorCode.OPERATION_ERROR, 状态转换异常);}return this.getById(id);}Overridepublic Order deliver(int id) {Order order this.getById(id);log.info(发货order订单信息{}, order);if (!sendEvent(OrderStatusChangeEvent.DELIVERY, order)) {throw new BusinessException(ErrorCode.OPERATION_ERROR, 状态转换异常);}return this.getById(id);}Overridepublic Order receive(int id) {Order order this.getById(id);log.info(收货order订单信息{}, order);if (!sendEvent(OrderStatusChangeEvent.RECEIVED, order)) {throw new BusinessException(ErrorCode.OPERATION_ERROR, 状态转换异常);}return this.getById(id);}Overridepublic ListOrder getOrders() {return this.list();}/*** 发送订单状态转换事件* synchronized修饰保证这个方法是线程安全的** param changeEvent* param order* return*/private synchronized boolean sendEvent(OrderStatusChangeEvent changeEvent, Order order) {boolean result false;try {//启动状态机orderStateMachine.start();//尝试恢复状态机状态persister.restore(orderStateMachine, order);Message message MessageBuilder.withPayload(changeEvent).setHeader(order, order).build();result orderStateMachine.sendEvent(message);//持久化状态机状态persister.persist(orderStateMachine, order);} catch (Exception e) {log.error(订单操作失败:{}, e);} finally {orderStateMachine.stop();}return result;} }其实到这还需要思考一个问题在业务层通过状态机发送的只是订单转变事件只是订单状态改变的事件OrderStatusChangeEvent那么状态机怎么知道初始状态是什么因为需要靠初始状态判断是否达到体检可以转变状态。 这就需要配置状态机持久化配置了 /*** 持久化配置* 实际使用中可以配合redis等进行持久化操作** return*/ Bean public DefaultStateMachinePersister persister() {return new DefaultStateMachinePersister(new StateMachinePersistObject, Object, Order() {//这个内存中的示例仅用于演示目的。对于真正的应用程序你应该使用真正的持久存储实现。private MapLong, StateMachineContextObject, Object map new HashMap();Overridepublic void write(StateMachineContextObject, Object context, Order order) throws Exception {map.put(order.getId(), context);}Overridepublic StateMachineContextObject, Object read(Order order) throws Exception {return map.get(order.getId());}}); }首先状态机会触发read(Order order)方法在持久化存储中读取相应的状态机上下文。 这样状态机就能获取到的初始状态了。 而write(StateMachineContextObject, Object context, Order order)方法则是将订单ID对应的上下文放到map集合中去。 根据订单的初始状态和触发事件对应的目标状态执行相对应的状态机监听器事件。 然后将状态机修改后的订单状态的上下文通过write方法写进map中以便下一次订单状态流转的时候可以用到。 4.1 接口测试 一开始创建一个订单订单状态为1也就是待付款。 接着调用支付接口触发支付事件订单状态流转为2也就是待发货 如果这时候不调用发货接口直接调用收货接口订单状态会不会改变呢 很明显不会状态机会识别到状态流转异常在sendEvent会返回false表示失败接着业务层抛出异常。 继续调用发货接口订单触发发货事件订单状态转变为3也就是待收货状态。 最后收货整个订单状态流转过程就完美完成了 5. 总结 Spring StateMachine是Spring旗下的一个状态机框架。所以生态非常丰富与Spring整合度非常高非常适合结合Spring框架去使用。 但是Spring StateMachine定制性难度困难因为Spring StateMachine是一个复杂的框架各方面来说难以定制化。 所以如果是直接使用状态机的组件库可以考虑使用Spring的状态机。 参考 Squirrel状态机-从原理探究到最佳实践 - 掘金 (juejin.cn)状态机的介绍和使用 | 京东物流技术团队 - 掘金 (juejin.cn)Spring之状态机讲解_spring状态机_爱吃牛肉的大老虎的博客-CSDN博客Spring StateMachine 文档 | 中文文档 (gitcode.host)【设计模式】软件设计原则以及23种设计模式总结_起名方面没有灵感的博客-CSDN博客使用Spring StateMachine框架实现状态机 (taodudu.cc)
http://www.sczhlp.com/news/216426/

相关文章:

  • 爱站seo工具包官网辽宁seo推广软件
  • 网站宣传海报wordpress 文章目录插件免费版
  • 个体户营业执照科研做企业网站吗网站建设的新发展
  • 移动商城网站开发选择解决wordpress需要ftp
  • 旅游营销网站开发78建筑网官网
  • 免费隐私网站推广怎样做才能让百度搜到网站产品
  • 专业网站开发企业赣州哪里做网站
  • js特效网站模板做碳循环的网站
  • 宠物网站制作内容来年做那些网站能致富
  • 珠海网站建设公司哪个好大气的企业网站源码
  • 网站建设讯美深圳市建设工程交易中心网站
  • 周村区建设网站上海招投标网官方
  • 织梦网站怎么做301跳转地方门户网站如何推广
  • 可以以个人名义做网站么开发微信微网站建设
  • 地方房地产网站基于php mysql的网站开发
  • 网站后台登入模板网页制作教程视频 网盘
  • 给网站做备案wordpress引导页插件
  • flash网站建设教程视频策划书用什么软件做
  • 健身网站开发开题报告对网站建设的评价语
  • 怎样提高网站首页权重做外贸采购都是用什么网站
  • 儿童摄影作品网站国内哪个推广网站做的好
  • 运城推广型网站开发pc微信二维码永久入口
  • 西安知名的集团门户网站建设费用企业的网站内容管理系统
  • 如何创建一个自己的网页宁波seo在线优化哪家好
  • 网站字体一般是什么字体响应式网站一般怎么设计
  • arp 断网小实验
  • 2025 年箱变压器厂家最新推荐榜单:涵盖非晶合金铁心、三相、矿用等多类型设备,助力采购方精准筛选优质合作企业
  • 从“人防”到“智防”:EasyCVR+煤矿AI智能分析一体机重塑矿山安全监管模式
  • 从Java工程师到AI工程师,我花了6个月的转型经验分享
  • 2025 年最新推荐配电柜源头厂家口碑排行榜:聚焦高压智能防爆等多类型产品,精选实力品牌助企业采购高压/智能/抽屉式/照明/防爆配电柜厂家推荐