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

做游戏网站淘宝关键词排名优化技巧

做游戏网站,淘宝关键词排名优化技巧,江苏网站建设教程,深圳平面设计培训一、什么是状态机 状态机是有限状态自动机的简称,是现实事物运行规则抽象而成的一个数学模型,是一种概念性机器,它能采取某种操作来响应一个外部事件。这种操作不仅能取决于接收到的事件,还能取决于各个事件的相对发生顺序。状态…

一、什么是状态机

状态机是有限状态自动机的简称,是现实事物运行规则抽象而成的一个数学模型,是一种概念性机器,它能采取某种操作来响应一个外部事件。这种操作不仅能取决于接收到的事件,还能取决于各个事件的相对发生顺序。状态机能够跟踪一个内部状态,这个状态会在收到事件后进行更新。因此,为一个事件而响应的行动不仅取决于事件本身,还取决于机器的内部状态。此外,采取的行动还会决定并更新机器的状态,这样一来,任何逻辑都可建模成一系列事件/状态组合。

状态机由以下几部分构成:

  • 状态(States):描述了系统可能存在的所有情况。
  • 事件(Events):触发状态转换的动作或者条件。
  • 动作(actions):当事件发生时,系统执行的动作或操作。
  • 转换(Transitions):描述了系统从一个状态到另一个状态的变化过程。

状态机的类型主要有两种:有限状态机(Finite State Machine, FSM)和推进自动机(Pushdown Automata)。有限状态机是最基本的状态机类型,它只能处于有限个状态中的一个。状态机的应用非常广泛,包括但不限于协议设计、游戏开发、硬件设计、用户界面设计和软件工程等领域。

状态机图包含了六种元素:起始、终止、现态、条件、动作、次态(目标状态)。以下是一个订单的状态机图,以从待支付状态转换为待发货状态为例:

在这里插入图片描述

  • 现态:是指当前所处的状态。待支付
  • 条件:又称为“事件”,当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。支付事件
  • 动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。状态转换为待发货
  • 次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了,待发货。

有两点需要我们注意区分的事项:

  1. 避免把某个“程序动作”当作是一种“状态”来处理。那么如何区分“动作”和“状态”?“动作”是不稳定的,即使没有条件的触发,“动作”一旦执行完毕就结束了;而“状态”是相对稳定的,如果没有外部条件的触发,一个状态会一直持续下去。

  2. 状态划分时漏掉一些状态,导致跳转逻辑不完整。所以在设计状态机时,我们需要反复的查看设计的状态图或者状态表,最终达到一种牢不可破的设计方案。

二、spring状态机

spring官方为我们提供了一个状态机框架 Spring Statemachine。Spring Statemachine 是 Spring 框架中的一个模块,专门用于实现状态机模式。它提供了丰富的功能来简化状态机的创建、配置和管理,特别适合于那些需要复杂状态管理和转换的应用场景。以下是 Spring Statemachine 的一些核心特点和优势:

  1. 高度集成
    Spring Statemachine 与 Spring 生态系统紧密集成,可以方便地利用 Spring 的依赖注入、事件发布/订阅等功能。
    支持与 Spring Boot 应用无缝集成,简化配置和部署过程。
  2. 配置灵活
    支持基于 Java API 和 XML 配置两种方式来定义状态机模型,包括状态、事件、转换和动作。
    提供了状态机构建器(StateMachineBuilder),允许以编程方式构建状态机模型。
  3. 事件驱动
    基于事件驱动模型,当状态机接收到外部事件时,会根据配置自动执行状态转换和关联的动作。
    支持内部事件和外部事件,便于解耦状态机逻辑与其他组件。
  4. 状态监听和动作
    允许在状态进入、退出时执行自定义逻辑(动作),以及在状态转换前后执行动作。
    支持状态改变监听器,可以监控状态机的运行时状态变化。
  5. 并发支持
    支持多线程环境下的状态机实例管理,可以为每个会话或请求创建独立的状态机实例。
    提供并发策略配置,以适应不同的并发需求。
  6. 可视化和调试
    可以生成状态机的可视化模型,帮助开发者和业务人员理解状态机逻辑。
    支持状态机执行跟踪,便于调试和分析状态机行为。
  7. 扩展性
    提供了丰富的扩展点,允许开发者根据需要定制状态机的行为,如自定义决策逻辑、动作执行器等。
    支持与Spring Integration等其他Spring项目集成,进一步扩展应用功能。
  8. 持久化和恢复
    支持状态机状态的持久化,可以在应用重启后恢复到之前的状态。对于需要长期运行并保持状态的应用尤为重要。

通过使用 Spring Statemachine,开发者可以高效地构建和管理复杂的状态逻辑,同时保持代码的清晰度和可维护性。

三、代码实践

笔者这里还是以订单流转为例,使用springboot应用,简单展示spring状态机的用法。
下面展示的是主要核心代码,部分代码笔者没有展示了,完整代码库gitee地址
:代码地址

3.1 建表tb_order

CREATE TABLE `tb_order` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',`order_code` varchar(128) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '订单编码',`status` smallint(3) DEFAULT NULL COMMENT '订单状态',`name` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '订单名称',`price` decimal(12,2) DEFAULT NULL COMMENT '价格',`delete_flag` tinyint(2) NOT NULL DEFAULT '0' COMMENT '删除标记,0未删除  1已删除',`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` timestamp  COMMENT '更新时间',`create_user_code` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '创建人',`update_user_code` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '更新人',`version` int(11) NOT NULL DEFAULT '0' COMMENT '版本号',`remark` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '备注',PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='订单表';

3.2 建立Spring Statemachine项目

笔者新建了一个spring-machine的springboot项目,因为要操作数据库,引入了jdbc和mybatis依赖。

yaml配置

server:port: 4455spring:datasource:hikari:connection-timeout: 6000000 # 设置为60000毫秒,即60秒# 数据库连接信息driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/spring-machine?useSSL=false&serverTimezone=UTCusername: rootpassword: rootdata:redis:# Redis服务器地址host: localhost# Redis服务器端口号port: 6379# 使用的数据库索引,默认是0database: 0# 连接超时时间timeout: 1800000# 设置密码password:lettuce:pool:# 最大阻塞等待时间,负数表示没有限制max-wait: -1# 连接池中的最大空闲连接max-idle: 5# 连接池中的最小空闲连接min-idle: 0# 连接池中最大连接数,负数表示没有限制max-active: 20
mybatis:# MyBatis配置mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.spring.statemachine.mapperconfiguration:map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImpl

引入依赖

注意,笔者用的依赖基本都是最新的,使用的jdk是21,源码下载后根据个人环境版本配置做相应版本修改,直至不报错

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-undertow</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId></dependency><!-- redis持久化状态机 --><dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-redis</artifactId><version>1.2.14.RELEASE</version></dependency><!--状态机--><!--spring statemachine--><dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-core</artifactId><version>4.0.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.50</version> <!-- 确保使用最新的版本 --></dependency><!-- Spring AOP --><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>6.1.8</version> <!-- 替换为实际使用的Spring版本 --></dependency><!-- AspectJ --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.9.22</version> <!-- 替换为实际使用的AspectJ版本 --></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.22</version> <!-- 替换为实际使用的AspectJ版本 --></dependency>

订单状态枚举类

package com.spring.statemachine.orderEnum;public enum OrderStatus {// 待支付,待发货,待收货,已完成WAIT_PAYMENT(1, "待支付"),WAIT_DELIVER(2, "待发货"),WAIT_RECEIVE(3, "待收货"),FINISH(4, "已完成");private final Integer key;private final String desc;OrderStatus(Integer key, String desc) {this.key = key;this.desc = desc;}public Integer getKey() {return key;}public String getDesc() {return desc;}public static OrderStatus getByKey(Integer key) {for (OrderStatus e : values()) {if (e.getKey().equals(key)) {return e;}}throw new RuntimeException("enum not exists.");}
}

事件枚举

package com.spring.statemachine.orderEnum;public enum OrderStatusChangeEvent {// 支付,发货,确认收货PAYED, DELIVERY, RECEIVED;
}

定义状态机规则和配置状态机

package com.spring.statemachine.config;import com.spring.statemachine.orderEnum.OrderStatus;
import com.spring.statemachine.orderEnum.OrderStatusChangeEvent;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;import java.util.EnumSet;@Configuration
@EnableStateMachine(name = "orderStateMachine")
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderStatus, OrderStatusChangeEvent> {/*** 配置状态*/public void configure(StateMachineStateConfigurer<OrderStatus, OrderStatusChangeEvent> states) throws Exception {states.withStates().initial(OrderStatus.WAIT_PAYMENT).states(EnumSet.allOf(OrderStatus.class));}/*** 配置状态转换事件关系*/public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderStatusChangeEvent> transitions) throws Exception {transitions//支付事件:待支付-》待发货.withExternal().source(OrderStatus.WAIT_PAYMENT).target(OrderStatus.WAIT_DELIVER).event(OrderStatusChangeEvent.PAYED).and()//发货事件:待发货-》待收货.withExternal().source(OrderStatus.WAIT_DELIVER).target(OrderStatus.WAIT_RECEIVE).event(OrderStatusChangeEvent.DELIVERY).and()//收货事件:待收货-》已完成.withExternal().source(OrderStatus.WAIT_RECEIVE).target(OrderStatus.FINISH).event(OrderStatusChangeEvent.RECEIVED);}
}

配置持久化

package com.spring.statemachine.config;import com.alibaba.fastjson.JSON;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.statemachine.StateMachineContext;
import org.springframework.statemachine.StateMachinePersist;
import org.springframework.statemachine.persist.DefaultStateMachinePersister;
import org.springframework.statemachine.persist.RepositoryStateMachinePersist;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.statemachine.redis.RedisStateMachineContextRepository;
import org.springframework.statemachine.redis.RedisStateMachinePersister;import java.util.HashMap;
import java.util.Map;@Configuration
@Slf4j
public class Persist<E, S> {@Resourceprivate RedisConnectionFactory redisConnectionFactory;/*** 持久化到内存map中*/@Bean(name = "stateMachineMemPersister")@SuppressWarnings("all")public static StateMachinePersister getPersister() {return new DefaultStateMachinePersister(new StateMachinePersist() {private final Map<Object, StateMachineContext> map = new HashMap<>();@Overridepublic void write(StateMachineContext context, Object contextObj) throws Exception {log.info("持久化状态机,context:{},contextObj:{}", JSON.toJSONString(context), JSON.toJSONString(contextObj));map.put(contextObj, context);}@Overridepublic StateMachineContext read(Object contextObj) throws Exception {log.info("获取状态机,contextObj:{}", JSON.toJSONString(contextObj));StateMachineContext stateMachineContext = map.get(contextObj);log.info("获取状态机结果,stateMachineContext:{}", JSON.toJSONString(stateMachineContext));return stateMachineContext;}});}/*** 持久化到redis中,在分布式系统中使用*/@Bean(name = "stateMachineRedisPersister")public RedisStateMachinePersister<E, S> getRedisPersister() {RedisStateMachineContextRepository<E, S> repository = new RedisStateMachineContextRepository<>(redisConnectionFactory);RepositoryStateMachinePersist<E, S> p = new RepositoryStateMachinePersist<>(repository);return new RedisStateMachinePersister<>(p);}
}

业务系统controller

package com.spring.statemachine.controller;import com.spring.statemachine.domain.Order;
import com.spring.statemachine.service.OrderService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/order")
public class OrderController {@Resourceprivate OrderService orderService;/*** 根据id查询订单*/@RequestMapping("/getById")public Order getById(@RequestParam("id") Long id) {//根据id查询订单return orderService.getById(id);}/*** 创建订单*/@RequestMapping("/create")public String create(@RequestBody Order order) {//创建订单orderService.create(order);return "success";}/*** 对订单进行支付*/@RequestMapping("/pay")public String pay(@RequestParam("id") Long id) {//对订单进行支付orderService.pay(id);return "success";}/*** 对订单进行发货*/@RequestMapping("/deliver")public String deliver(@RequestParam("id") Long id) {//对订单进行确认收货orderService.deliver(id);return "success";}/*** 对订单进行确认收货*/@RequestMapping("/receive")public String receive(@RequestParam("id") Long id) {//对订单进行确认收货orderService.receive(id);return "success";}
}

service服务

package com.spring.statemachine.service.impl;import com.spring.statemachine.domain.Order;
import com.spring.statemachine.interfaceVariable.CommonConstants;
import com.spring.statemachine.mapper.OrderMapper;
import com.spring.statemachine.orderEnum.OrderStatus;
import com.spring.statemachine.orderEnum.OrderStatusChangeEvent;
import com.spring.statemachine.service.OrderService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;import java.util.Objects;@Service("orderService")
@Slf4j
public class OrderServiceImpl implements OrderService {@Resourceprivate StateMachine<OrderStatus, OrderStatusChangeEvent> orderStateMachine;@Resourceprivate StateMachinePersister<OrderStatus, OrderStatusChangeEvent, String> stateMachineMemPersister;@Resourceprivate StateMachinePersister<OrderStatus, OrderStatusChangeEvent, String> stateMachineRedisPersister;@Resourceprivate OrderMapper orderMapper;/*** 创建订单*/public Order create(Order order) {order.setStatus(OrderStatus.WAIT_PAYMENT.getKey());orderMapper.insert(order);return order;}/*** 对订单进行支付*/public void pay(Long id) {Order order = orderMapper.selectById(id);log.info("线程名称:{},尝试支付,订单号:{}", Thread.currentThread().getName(), id);if (!sendEvent(OrderStatusChangeEvent.PAYED, order,CommonConstants.payTransition)) {log.error("线程名称:{},支付失败, 状态异常,订单信息:{}", Thread.currentThread().getName(), order);throw new RuntimeException("支付失败, 订单状态异常");}}/*** 对订单进行发货*/public void deliver(Long id) {Order order = orderMapper.selectById(id);log.info("线程名称:{},尝试发货,订单号:{}", Thread.currentThread().getName(), id);if (!sendEvent(OrderStatusChangeEvent.DELIVERY, order,CommonConstants.deliverTransition)) {log.error("线程名称:{},发货失败, 状态异常,订单信息:{}", Thread.currentThread().getName(), order);throw new RuntimeException("发货失败, 订单状态异常");}}@Overridepublic Order getById(Long id) {return orderMapper.selectById(id);}/*** 对订单进行确认收货*/public void receive(Long id) {Order order = orderMapper.selectById(id);log.info("线程名称:{},尝试收货,订单号:{}", Thread.currentThread().getName(), id);if (!sendEvent(OrderStatusChangeEvent.RECEIVED, order,CommonConstants.receiveTransition)) {log.error("线程名称:{},收货失败, 状态异常,订单信息:{}", Thread.currentThread().getName(), order);throw new RuntimeException("收货失败, 订单状态异常");}}/*** 发送订单状态转换事件* synchronized修饰保证这个方法是线程安全的*/private synchronized boolean sendEvent(OrderStatusChangeEvent changeEvent, Order order,String key) {boolean result = false;try {//启动状态机orderStateMachine.startReactively();//内存持久化状态机尝试恢复状态机状态,单机环境下使用//stateMachineMemPersister.restore(orderStateMachine, String.valueOf(order.getId()));//redis持久化状态机尝试恢复状态机状态,分布式环境下使用stateMachineRedisPersister.restore(orderStateMachine, String.valueOf(order.getId()));Message<OrderStatusChangeEvent> message = MessageBuilder.withPayload(changeEvent).setHeader(CommonConstants.orderHeader, order).build();result = orderStateMachine.sendEvent(message);if(!result){return false;}//获取到监听的结果信息Integer o = (Integer) orderStateMachine.getExtendedState().getVariables().get(key + order.getId());//操作完成之后,删除本次对应的key信息orderStateMachine.getExtendedState().getVariables().remove(key+order.getId());//如果事务执行成功,则持久化状态机if(Objects.equals(1, o)){//使用内存持久化状态机状态,单机环境下使用//stateMachineMemPersister.persist(orderStateMachine, String.valueOf(order.getId()));//使用redis持久化状态机状态机状态,分布式环境下使用stateMachineRedisPersister.persist(orderStateMachine, String.valueOf(order.getId()));}else {//订单执行业务异常return false;}} catch (Exception e) {log.error("订单操作失败:{}", e.getMessage(),e);} finally {orderStateMachine.stopReactively();}return result;}
}

注解和切面类

注解

package com.spring.statemachine.aspect;import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;@Retention(RetentionPolicy.RUNTIME)
public @interface LogResult {/*** 执行的业务key** @return String*/String key();
}

切面类

package com.spring.statemachine.aspect;import com.spring.statemachine.domain.Order;
import com.spring.statemachine.interfaceVariable.CommonConstants;
import com.spring.statemachine.orderEnum.OrderStatus;
import com.spring.statemachine.orderEnum.OrderStatusChangeEvent;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.messaging.Message;
import org.springframework.statemachine.StateMachine;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;/*** 本注解主要是把OrderStateListener中注释的重复代码提取出来*/
@Component
@Aspect
@Slf4j
public class LogResultAspect {@Pointcut("@annotation(com.spring.statemachine.aspect.LogResult)")private void logResultPointCut() {//logResultPointCut 日志注解切点}@Resourceprivate StateMachine<OrderStatus, OrderStatusChangeEvent> orderStateMachine;@Around("logResultPointCut()")@SuppressWarnings("all")public Object logResultAround(ProceedingJoinPoint pjp) throws Throwable {//获取参数Object[] args = pjp.getArgs();log.info("参数args:{}", args);Message message = (Message) args[0];Order order = (Order) message.getHeaders().get(CommonConstants.orderHeader);//获取方法Method method = ((MethodSignature) pjp.getSignature()).getMethod();LogResult logResult = method.getAnnotation(LogResult.class);String key = logResult.key();Object returnVal;try {//执行方法returnVal = pjp.proceed();//如果业务执行正常,则保存信息//成功 则为1assert order != null;orderStateMachine.getExtendedState().getVariables().put(key + order.getId(), 1);} catch (Throwable e) {log.error("e:{}", e.getMessage());//如果业务执行异常,则保存信息//将异常信息变量信息中,失败则为0assert order != null;orderStateMachine.getExtendedState().getVariables().put(key + order.getId(), 0);throw e;}return returnVal;}
}

状态变化监听

package com.spring.statemachine.listener;import com.spring.statemachine.aspect.LogResult;
import com.spring.statemachine.domain.Order;
import com.spring.statemachine.interfaceVariable.CommonConstants;
import com.spring.statemachine.mapper.OrderMapper;
import com.spring.statemachine.orderEnum.OrderStatus;
import com.spring.statemachine.orderEnum.OrderStatusChangeEvent;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.Message;
//import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.annotation.OnTransition;
import org.springframework.statemachine.annotation.WithStateMachine;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;/*** 订单事件监听器(注释调的代码替换为aop拦截实现LogResultAspect)*/
@Component("orderStateListener")
@WithStateMachine(name = "orderStateMachine")
@Slf4j
public class OrderStateListener {@Resourceprivate OrderMapper orderMapper;
//    @Resource
//    private StateMachine<OrderStatus, OrderStatusChangeEvent> orderStateMachine;/*** 支付事件监听*/@OnTransition(source = "WAIT_PAYMENT", target = "WAIT_DELIVER")@Transactional(rollbackFor = Exception.class)@LogResult(key = CommonConstants.payTransition)public void payTransition(Message<OrderStatusChangeEvent> message) {Order order = (Order) message.getHeaders().get(CommonConstants.orderHeader);log.info("支付,状态机反馈信息:{}", message.getHeaders());//更新订单assert order != null;order.setStatus(OrderStatus.WAIT_DELIVER.getKey());orderMapper.updateById(order);
//        try {
//            //更新订单
//            assert order != null;
//            order.setStatus(OrderStatus.WAIT_DELIVER.getKey());
//            orderMapper.updateById(order);
//            //成功 则为1
//            orderStateMachine.getExtendedState().getVariables().put(CommonConstants.payTransition+order.getId(),1);
//        } catch (Exception e) {
//            //如果出现异常,则进行回滚
//            log.error("payTransition 出现异常:{}",e.getMessage(),e);
//            //将异常信息变量信息中,失败则为0
//            orderStateMachine.getExtendedState().getVariables().put(CommonConstants.payTransition+order.getId(), 0);
//            throw e;
//        }}/*** 发货事件监听*/@OnTransition(source = "WAIT_DELIVER", target = "WAIT_RECEIVE")@LogResult(key = CommonConstants.deliverTransition)public void deliverTransition(Message<OrderStatusChangeEvent> message) {Order order = (Order) message.getHeaders().get(CommonConstants.orderHeader);log.info("发货,状态机反馈信息:{}", message.getHeaders());//更新订单assert order != null;order.setStatus(OrderStatus.WAIT_RECEIVE.getKey());orderMapper.updateById(order);
//        try {
//            //更新订单
//            assert order != null;
//            order.setStatus(OrderStatus.WAIT_RECEIVE.getKey());
//            orderMapper.updateById(order);
//            //成功 则为1
//            orderStateMachine.getExtendedState().getVariables().put(CommonConstants.deliverTransition+order.getId(),1);
//        } catch (Exception e) {
//            //如果出现异常,则进行回滚
//            log.error("payTransition 出现异常:{}",e.getMessage(),e);
//            //将异常信息变量信息中,失败则为0
//            orderStateMachine.getExtendedState().getVariables().put(CommonConstants.deliverTransition+order.getId(), 0);
//            throw e;
//        }}/*** 确认收货事件监听*/@OnTransition(source = "WAIT_RECEIVE", target = "FINISH")@LogResult(key = CommonConstants.receiveTransition)public void receiveTransition(Message<OrderStatusChangeEvent> message) {Order order = (Order) message.getHeaders().get(CommonConstants.orderHeader);log.info("确认收货,状态机反馈信息:{}", message.getHeaders());//更新订单assert order != null;order.setStatus(OrderStatus.FINISH.getKey());orderMapper.updateById(order);
//        try {
//            //更新订单
//            assert order != null;
//            order.setStatus(OrderStatus.FINISH.getKey());
//            orderMapper.updateById(order);
//            //成功 则为1
//            orderStateMachine.getExtendedState().getVariables().put(CommonConstants.receiveTransition+order.getId(),1);
//        } catch (Exception e) {
//            //如果出现异常,则进行回滚
//            log.error("payTransition 出现异常:{}",e.getMessage(),e);
//            //将异常信息变量信息中,失败则为0
//            orderStateMachine.getExtendedState().getVariables().put(CommonConstants.receiveTransition+order.getId(), 0);
//            throw e;
//        }}
}

四、验证修改

主体流程

  • 新增一个订单
 http://localhost:8084/order/create
  • 对订单进行支付
http://localhost:8084/order/pay?id=2
  • 对订单进行发货
 http://localhost:8084/order/deliver?id=2
  • 对订单进行确认收货
http://localhost:8084/order/receive?id=2

具体实施步骤如下:

新增订单

工具为postman(一款非常强大好用的接口测试工具,地址:postman官网)

json格式的数据

{"id": 3,"orderCode": "ORDER-3","name": "Product C","price": "199.99","deleteFlag": 0,"createTime": "2024-05-24T14:41:00Z","updateTime": "2024-05-25T11:18:00Z","createUserCode": "USER123","updateUserCode": "USER456","version": 1,"remark": "Sample order for testing"
}

在这里插入图片描述

使用新增订单接口http://localhost:8084/order/create创建了几个订单
在这里插入图片描述

支付订单

对id为2的订单进行支付
在这里插入图片描述
控制台信息如下
在这里插入图片描述

查看数据库,id为2的订单状态,已被修改为2待发货状态

在这里插入图片描述
对于这个id为2的订单,我们再次调用支付,会发生什么?
在这里插入图片描述
可以看到已经支付的订单,无法再次支付了。

持久化方式

笔者选择的是redis的方式持久化状态机,当然也有内存持久化的方式,前者适用于分布式,后者适用于单机环境。比如同一个订单支付操作,第二次再重复支付,二者都会报错,但是redis持久化方式,服务重启重复支付会继续报错,而内存持久化方式,服务重启后,再进行重复支付操作,却不会报错了,因为内存中缓存的状态机状态随着服务重启重置了,而redis缓存仍然存在。

redis持久化的key即为订单的id
在这里插入图片描述

总结:以上就是spring statemachine的一个简单示例,对于复杂流程控制和处理的业务逻辑很有用处,应该通过这个案例掌握使用方法。


文章转载自:
http://dinncoschillerize.stkw.cn
http://dinncoineligible.stkw.cn
http://dinncoexchangeable.stkw.cn
http://dinncobottomry.stkw.cn
http://dinncohygeia.stkw.cn
http://dinncointermedin.stkw.cn
http://dinncoprosody.stkw.cn
http://dinncoloanblend.stkw.cn
http://dinncointelligence.stkw.cn
http://dinncoanion.stkw.cn
http://dinncoshotmaking.stkw.cn
http://dinncoinhospitable.stkw.cn
http://dinncotimidly.stkw.cn
http://dinncocordwain.stkw.cn
http://dinncoforbiddance.stkw.cn
http://dinncoaesc.stkw.cn
http://dinncojudgmatic.stkw.cn
http://dinncoafrikaans.stkw.cn
http://dinncothelma.stkw.cn
http://dinncokhedah.stkw.cn
http://dinncosporogenic.stkw.cn
http://dinncoitalia.stkw.cn
http://dinncomegaloblast.stkw.cn
http://dinncolias.stkw.cn
http://dinncotussore.stkw.cn
http://dinncocellulate.stkw.cn
http://dinncosclerosing.stkw.cn
http://dinncoblousy.stkw.cn
http://dinncoexteriority.stkw.cn
http://dinncoskutterudite.stkw.cn
http://dinncoadrenotropic.stkw.cn
http://dinncoyamasee.stkw.cn
http://dinncorigor.stkw.cn
http://dinncocole.stkw.cn
http://dinncosensatory.stkw.cn
http://dinncojonson.stkw.cn
http://dinncooestrone.stkw.cn
http://dinncoconferment.stkw.cn
http://dinncoisospory.stkw.cn
http://dinncocameronian.stkw.cn
http://dinncotraducianism.stkw.cn
http://dinncofrowardly.stkw.cn
http://dinncowaterish.stkw.cn
http://dinncosquamulose.stkw.cn
http://dinncojagatai.stkw.cn
http://dinncobenthograph.stkw.cn
http://dinncolegendize.stkw.cn
http://dinncocolossians.stkw.cn
http://dinncocystoscope.stkw.cn
http://dinncostate.stkw.cn
http://dinncobrad.stkw.cn
http://dinncobloodlust.stkw.cn
http://dinncotaphonomy.stkw.cn
http://dinncorider.stkw.cn
http://dinncoscoreline.stkw.cn
http://dinncogramineous.stkw.cn
http://dinncopathos.stkw.cn
http://dinncowostteth.stkw.cn
http://dinncoknuckle.stkw.cn
http://dinncoflintiness.stkw.cn
http://dinncozucchini.stkw.cn
http://dinncophlegmatized.stkw.cn
http://dinncoalum.stkw.cn
http://dinncooverpopulation.stkw.cn
http://dinncoplenilune.stkw.cn
http://dinncogumban.stkw.cn
http://dinncoadmiralty.stkw.cn
http://dinncoleant.stkw.cn
http://dinncocoteau.stkw.cn
http://dinncobronchitis.stkw.cn
http://dinncothremmatology.stkw.cn
http://dinncorazorbill.stkw.cn
http://dinncoseverely.stkw.cn
http://dinncoitalianate.stkw.cn
http://dinnconothing.stkw.cn
http://dinncolesser.stkw.cn
http://dinncosorely.stkw.cn
http://dinncopullicat.stkw.cn
http://dinncoquasimodo.stkw.cn
http://dinncosantonin.stkw.cn
http://dinncograftabl.stkw.cn
http://dinncodivertingly.stkw.cn
http://dinncobusinessman.stkw.cn
http://dinncoindult.stkw.cn
http://dinncoprevision.stkw.cn
http://dinncolobeliaceous.stkw.cn
http://dinncotheatrician.stkw.cn
http://dinncodaemonic.stkw.cn
http://dinncounending.stkw.cn
http://dinncosociolect.stkw.cn
http://dinncothriftlessly.stkw.cn
http://dinncohorologii.stkw.cn
http://dinncoplowshoe.stkw.cn
http://dinncokaraism.stkw.cn
http://dinncopulsimeter.stkw.cn
http://dinncosilty.stkw.cn
http://dinncosalop.stkw.cn
http://dinnconeotype.stkw.cn
http://dinncopekinese.stkw.cn
http://dinncostrass.stkw.cn
http://www.dinnco.com/news/93729.html

相关文章:

  • 网站网站建设那个推广平台好用
  • 网站定制的公司如何开网店
  • 廊坊网站建设廊坊seo门户网站
  • 90设计网站最便宜终身资源搜索
  • 政府网站内容建设管理规范球队世界排名榜
  • 北京的制作网站的公司有哪些网站如何添加友情链接
  • 龙岗高端建设网站建设最常用的网页制作软件
  • 个人主页文案东莞百度快速排名优化
  • 昆明企业网站建设公司百度店铺
  • 做网站需要什么系统谷歌流量代理代理
  • 做网站赚钱 知乎爱站网工具
  • 做网站流程、网站诊断分析
  • 专业网站建设模板凡科建站教程
  • 18.ppt网站是谁做的怎样注册自己的网站
  • 摄影网站建设内容营销活动推广方案
  • 网站建设教程最新资讯百度链接提交
  • 对做的网站的改进建议磁力猫torrent kitty
  • 个人网站建设策划书网络营销策略有哪五种
  • 元做网站搜索引擎优化简历
  • 交互网站建设文军seo
  • 做网站怎么写预算站长工具端口
  • 免费网站中文源码下载seo优化推广业务员招聘
  • 合肥中小型企业网站建设方案模板简单的个人主页网站制作
  • 广州市网站制作备案查询官网
  • 运城推广型网站开发排名查询
  • 武汉网站制作谁家好网站优化检测
  • 青岛个人网站制作网络营销案例
  • 做空运货代常用网站网上推销产品的软件
  • 如何把网站加入白名单长沙网站建设
  • dw网页设计代码免费seo软文推广工具