spring 状态机

摘要:
认知状态->学习状态->进口机构.弹簧框架.圆柱齿轮.组件;importcom.qty.area.room.match.statemachine.RoomMatchState;ref=新对象引用<字符串;@PostConstructvoidinit(){ref.set(this);

前言:“状态机”见名知意,用状态去管理业务操作,打个比方:0~1岁(出生状态),1~3岁(认知状态),3~6岁(启蒙状态),6~22岁(学习状态),22~60(工作状态),60以后(退休状态),那么人一生成长经历则是(状态跳转):出生状态  -> 认知状态  -> 启蒙状态  -> 学习状态 ->  工作状态  -> 退休状态.

在每个状态中都会有不同的经历(事件),每个年龄就去干每个年龄的事情,背负这个年龄应该背负的责任,同时也享有这个年龄相应的乐趣(不同的状态去做不同的事情),直到离开这个世界(状态销毁)。

人的一生不可以倒退,但是:状态机可以,它可以在每个状态间互相跳转去做不同的事情,这样的好处:逻辑清晰、可以适当的控制并发、使整个事物更加通畅,好了,上代码:

1.新建状态机的辅助类:因为spring内部在redis中维护了一个状态机的hash表,所以必须接入redis

/*
 * o(-"-)o
 *
 * CopyRight(C) 2011 GameRoot Inc.
 *
 *
 *
 */
package com.qty.arena.helper.match.room;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.service.StateMachineService;
import org.springframework.stereotype.Component;

import com.qty.arena.core.ObjectReference;
import com.qty.arena.room.match.statemachine.RoomMatchEvent;
import com.qty.arena.room.match.statemachine.RoomMatchState;

/**
 * 队伍状态机持久化辅助类
 * 
 *
 * @data 2018年1月31日 下午2:22:58
 */
@Component
public class RoomMatchStateMachineHelper {

//    private static final Logger LOGGER = LoggerFactory.getLogger(TeamStateMachineHelper.class);

    private static final ObjectReference<RoomMatchStateMachineHelper> ref = new ObjectReference<RoomMatchStateMachineHelper>();
    
    /** 房间状态机参数传递通用DTO */
    public static final String ROOM_ACTION_DELIVERY_DTO = "room_action_delivery_dto";


//    @Autowired
//    private StateMachinePersist<RoomState, RoomEvent, String> stateMachinePersist;

    @Autowired
    private StateMachineService<RoomMatchState, RoomMatchEvent> roomMatchStateMachineService;

    @Autowired  
    private RedisTemplate<String, String> redisTemplate;
    
    @PostConstruct
    void init() {
        ref.set(this);
    }

    public static RoomMatchStateMachineHelper getInstance() {
        return ref.get();
    }
    
    /**
     * 获取状态机
     * 
     * @param machineId
     *            状态机编号
     * @return
     */
    public StateMachine<RoomMatchState, RoomMatchEvent> getStateMachine(String machineId) {
        return roomMatchStateMachineService.acquireStateMachine(machineId);
    }

//    /**
//     * 存储状态
//     * 
//     * @param machineId
//     *            状态机编号
//     * @throws Exception
//     */
//    public void save(String machineId) throws Exception {
//        StateMachineContext<RoomState, RoomEvent> stateMachineContext = stateMachinePersist.read(machineId);
//        stateMachinePersist.write(stateMachineContext, machineId);
//    }

    /**
     * 删除状态机
     * 
     * @param machineId
     *            状态机编号
     */
    public void delete(String machineId) {
        roomMatchStateMachineService.releaseStateMachine(machineId);
        redisTemplate.delete("RedisRepositoryStateMachine:" + machineId);
    }

    /**
     * 普通状态转换事件
     * 
     * @param machineId
     *            状态机编号
     * @param event
     *            事件
     */
    public StateMachine<RoomMatchState, RoomMatchEvent> sendEvent(String machineId, RoomMatchEvent event) {
        StateMachine<RoomMatchState, RoomMatchEvent> stateMachine = getStateMachine(machineId);
        if (stateMachine.sendEvent(event)) {
            return stateMachine;
        }
        return null;
    }

    /**
     * 传参的状态转换事件
     * 
     * @param machineId
     *            状态机编号
     * @param event
     *            事件
     * @param headerName
     *            传递参数的Key           
     * @param object
     *            传递的参数:对象
     */
    public StateMachine<RoomMatchState, RoomMatchEvent> sendEvent(String machineId, RoomMatchEvent event, String headerName, Object object) {
        StateMachine<RoomMatchState, RoomMatchEvent> stateMachine = getStateMachine(machineId);
        Message<RoomMatchEvent> message = MessageBuilder
                .withPayload(event)
                .setHeader(headerName, object)
                .build();
        //传递参数的事件
        if (stateMachine.sendEvent(message)) {
            return stateMachine;
        }
        return null;
    }
}

2.配置适配器

/*
 * o(-"-)o
 *
 * CopyRight(C) 2011 GameRoot Inc.
 *
 */
package com.qty.arena.room.custom.statemachine;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.statemachine.config.EnableStateMachineFactory;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.data.redis.RedisPersistingStateMachineInterceptor;
import org.springframework.statemachine.data.redis.RedisStateMachineRepository;
import org.springframework.statemachine.persist.StateMachineRuntimePersister;
import org.springframework.statemachine.service.DefaultStateMachineService;
import org.springframework.statemachine.service.StateMachineService;

import com.qty.arena.room.custom.statemachine.action.RoomCustomAlreadyDestroyEntryAction;
import com.qty.arena.room.custom.statemachine.action.RoomCustomAlreadySettlementEntryAction;
import com.qty.arena.room.custom.statemachine.action.RoomCustomCreateEntryAction;
import com.qty.arena.room.custom.statemachine.action.RoomCustomCreateLolInEntryAction;
import com.qty.arena.room.custom.statemachine.action.RoomCustomStartedEntryAction;
import com.qty.arena.room.custom.statemachine.action.RoomCustomVoteInEntryAction;

/**
 * 房间有限状态机适配器
 * 
 *
 * @data 2018年1月27日 上午10:30:42
 */
@EnableStateMachineFactory(name = "roomCustomStateMachineFactory")
public class RoomCustomStateMachineConfig extends EnumStateMachineConfigurerAdapter<RoomCustomState, RoomCustomEvent> {

    @Autowired
    private RedisStateMachineRepository redisStateMachineRepository;

    @Autowired
    private RoomCustomCreateEntryAction roomCustomCreateEntryAction;

    @Autowired
    private RoomCustomCreateLolInEntryAction roomCustomCreateLolInEntryAction;

    @Autowired
    private RoomCustomStartedEntryAction roomCustomStartedEntryAction;

    @Autowired
    private RoomCustomVoteInEntryAction roomCustomVoteInEntryAction;

    @Autowired
    private RoomCustomAlreadyDestroyEntryAction roomCustomAlreadyDestroyEntryAction;
    
    @Autowired
    private RoomCustomAlreadySettlementEntryAction roomCustomAlreadySettlementEntryAction;

    @Bean("roomCustomStateMachinePersist")
    public StateMachineRuntimePersister<RoomCustomState, RoomCustomEvent, String> stateMachinePersist() {
        return new RedisPersistingStateMachineInterceptor<RoomCustomState, RoomCustomEvent, String>(
                redisStateMachineRepository);
    }

    @Bean("roomCustomStateMachineService")
    public StateMachineService<RoomCustomState, RoomCustomEvent> stateMachineService(
            StateMachineFactory<RoomCustomState, RoomCustomEvent> stateMachineFactory) {
        return new DefaultStateMachineService<RoomCustomState, RoomCustomEvent>(stateMachineFactory,
                stateMachinePersist());
    }

    @Override
    public void configure(StateMachineConfigurationConfigurer<RoomCustomState, RoomCustomEvent> config)
            throws Exception {
        config.withPersistence().runtimePersister(stateMachinePersist());

        config.withMonitoring().monitor(new RoomCustomStateMachineMonitor());
    }

    @Override
    public void configure(StateMachineStateConfigurer<RoomCustomState, RoomCustomEvent> states) throws Exception {
        states.withStates()
            // 定义初始状态
            .initial(RoomCustomState.UNCREATED)
            // 定义状态机状态

            /** 已创建db房间状态 */
            .state(RoomCustomState.CREATED_DB_STATE, roomCustomCreateEntryAction, null)

            /** 创建Lol房间中状态 */
            .state(RoomCustomState.CREATE_LOL_IN, roomCustomCreateLolInEntryAction, null)

            /** 已开局状态 */
            .state(RoomCustomState.STARTED, roomCustomStartedEntryAction, null)

            /** 投票中状态 */
            .state(RoomCustomState.VOTE_IN, roomCustomVoteInEntryAction, null)
            
            /** 自定义房间已结算状态  */
            .state(RoomCustomState.ALREADY_SETTLEMENT, roomCustomAlreadySettlementEntryAction, null)

            /** 房间已销毁 */
            .state(RoomCustomState.ALREADY_DESTROY, roomCustomAlreadyDestroyEntryAction, null);

        // .states(EnumSet.allOf(RoomState.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<RoomCustomState, RoomCustomEvent> transitions)
            throws Exception {

        transitions

            // 初始化状态 -> 已创建 = 创建房间
            .withExternal()
            .source(RoomCustomState.UNCREATED)
            .target(RoomCustomState.CREATED_DB_STATE)
            .event(RoomCustomEvent.CREATE)
            .and()
            
            // 已创建 -> 已销毁 = 退出(最后一人)
            .withExternal()
            .source(RoomCustomState.CREATED_DB_STATE)
            .target(RoomCustomState.ALREADY_DESTROY)
            .event(RoomCustomEvent.DESTROY_ROOM_CUSTOM)
            .and()

            // 已创建 -> 已准备 = 全部准备
            .withExternal()
            .source(RoomCustomState.CREATED_DB_STATE)
            .target(RoomCustomState.CREATE_LOL_IN)
            .event(RoomCustomEvent.PREPARED_ALL)
            .and()

            // 创建Lol房间中状态 -> 已创建 = 创建lol房间定时任务3分钟
            .withExternal()
            .source(RoomCustomState.CREATE_LOL_IN)
            .target(RoomCustomState.CREATED_DB_STATE)
            .event(RoomCustomEvent.CREATE_LOL_ROOM_TASK)
            .and()

            // 创建lol房间中-> 已创建 = 退出
            .withExternal()
            .source(RoomCustomState.CREATE_LOL_IN)
            .target(RoomCustomState.CREATED_DB_STATE)
            .event(RoomCustomEvent.SIGN_OUT)
            .and()
            
            // 创建lol房间中 -> 已开局 = 已创建LOL房间
            .withExternal()
            .source(RoomCustomState.CREATE_LOL_IN)
            .target(RoomCustomState.STARTED)
            .event(RoomCustomEvent.GAME_ROOM_HAS_BEEN_CREATED)
            .and()
            
            // 已开局 -> 投票中 = 开始投票(6分钟)
            .withExternal()
            .source(RoomCustomState.STARTED)
            .target(RoomCustomState.VOTE_IN)
            .event(RoomCustomEvent.START_VOTE)
            .and()
            
            // 投票中 -> 已创建 = 全部投票
            .withExternal()
            .source(RoomCustomState.VOTE_IN)
            .target(RoomCustomState.CREATED_DB_STATE)
            .event(RoomCustomEvent.ALL_VOTE)
            .and()
            
            // 投票中 -> 已创建 = 全部投票
            .withExternal()
            .source(RoomCustomState.STARTED)
            .target(RoomCustomState.CREATED_DB_STATE)
            .event(RoomCustomEvent.ALL_VOTE)
            .and()
            
            //投票中 -> 已创建 = 结算延时任务(2小时)
            .withExternal()
            .source(RoomCustomState.VOTE_IN)
            .target(RoomCustomState.CREATED_DB_STATE)
            .event(RoomCustomEvent.SETTLEMENT_DELAY_TASK)
            .and()

            //投票中 -> 已结算 = 投票结算
            .withExternal()
            .source(RoomCustomState.VOTE_IN)
            .target(RoomCustomState.ALREADY_SETTLEMENT)
            .event(RoomCustomEvent.VOTE_SETTLEMENT)
            .and()
            
            //投票中 -> 已结算 = 查询结算
            .withExternal()
            .source(RoomCustomState.VOTE_IN)
            .target(RoomCustomState.ALREADY_SETTLEMENT)
            .event(RoomCustomEvent.QUERY_SETTLEMENT)
            .and()
            
            //投票中 -> 已结算 = 投票取消比赛(退还所有人蜜汁)
            .withExternal()
            .source(RoomCustomState.VOTE_IN)
            .target(RoomCustomState.ALREADY_SETTLEMENT)
            .event(RoomCustomEvent.VOTE_RETURN_MONEY)
            .and()
            
            //已开局 -> 已结算 = 投票取消比赛(退还所有人蜜汁)
            .withExternal()
            .source(RoomCustomState.STARTED)
            .target(RoomCustomState.ALREADY_SETTLEMENT)
            .event(RoomCustomEvent.VOTE_RETURN_MONEY)
            .and()
            
            //已结算 -> 已创建 = 全部投票
            .withExternal()
            .source(RoomCustomState.ALREADY_SETTLEMENT)
            .target(RoomCustomState.CREATED_DB_STATE)
            .event(RoomCustomEvent.ALL_VOTE)
            .and()
            
            //已结算 -> 已创建 = 结算延时任务(2小时)
            .withExternal()
            .source(RoomCustomState.ALREADY_SETTLEMENT)
            .target(RoomCustomState.CREATED_DB_STATE)
            .event(RoomCustomEvent.SAVE_RECORD_DELAY_TASK)
            .and()
            ;
    }
}

3.Action

package com.qty.arena.room.custom.statemachine.action;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.action.Action;
import org.springframework.stereotype.Component;

import com.qty.arena.dto.RoomCustomActionDeliveryDTO;
import com.qty.arena.helper.custom.room.RoomCustomCreateLolTaskHelper;
import com.qty.arena.helper.custom.room.RoomCustomSignOutHelper;
import com.qty.arena.helper.custom.room.RoomCustomStateMachineHelper;
import com.qty.arena.helper.custom.room.RoomCustomVoteReturnRoomHelper;
import com.qty.arena.room.custom.statemachine.RoomCustomEvent;
import com.qty.arena.room.custom.statemachine.RoomCustomState;

/**
 * 已创建db房间状态
 * 
 * @author yanLong.Li
 * @date 2018年11月10日 下午8:28:37
 */
@Component
public class RoomCustomCreateEntryAction implements Action<RoomCustomState, RoomCustomEvent> {

    @Autowired
    private RoomCustomCreateLolTaskHelper roomCustomCreateLolTaskHelper;

    @Autowired
    private RoomCustomSignOutHelper roomCustomSignOutHelper;

    @Autowired
    private RoomCustomVoteReturnRoomHelper roomCustomVoteReturnRoomHelper;

    @Override
    public void execute(StateContext<RoomCustomState, RoomCustomEvent> context) {
        Object object = context.getMessageHeader(RoomCustomStateMachineHelper.ROOM_ACTION_DELIVERY_DTO);
        if (!(object instanceof RoomCustomActionDeliveryDTO)) {
            return;
        }
        RoomCustomEvent event = context.getEvent();
        RoomCustomActionDeliveryDTO roomCustomActionDeliveryDTO = (RoomCustomActionDeliveryDTO) object;
        logic(roomCustomActionDeliveryDTO, event);
    }

    private void logic(RoomCustomActionDeliveryDTO roomCustomActionDeliveryDTO , RoomCustomEvent event) {
        if(event == RoomCustomEvent.CREATE_LOL_ROOM_TASK) {            
            roomCustomCreateLolTaskHelper.createLolTask(roomCustomActionDeliveryDTO);            
        }/*else if(event == RoomCustomEvent.SETTLEMENT_DELAY_TASK) {
            RoomCustomDTO roomCustomDTO = roomCustomActionDeliveryDTO.getRoomCustomDTO();
            roomCustomHelper.settlementAndSaveRecord(roomCustomDTO);
        }else if(event == RoomCustomEvent.SAVE_RECORD_DELAY_TASK) {
            RoomCustomDTO roomCustomDTO = roomCustomActionDeliveryDTO.getRoomCustomDTO();
            roomCustomHelper.saveRecord(roomCustomDTO);
        }*/else if(event == RoomCustomEvent.SIGN_OUT) {
            roomCustomSignOutHelper.preparedSignOut(roomCustomActionDeliveryDTO);
        }else if(event == RoomCustomEvent.ALL_VOTE) {
            roomCustomVoteReturnRoomHelper.execute(roomCustomActionDeliveryDTO);
        }
    }
}

4.演示调用

TeamMatchStateMachineHelper.getInstance().sendEvent(teamMatch.getStateMachineId(), TeamMatchEvent.CREATE
            , TeamMatchStateMachineHelper.TEAM_ACTION_DELIVERY, TeamMatchActionDeliveryDTO.valueOf(teamMatch, arena.getId()));

免责声明:文章转载自《spring 状态机》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇css下拉菜单、过渡tp3.2单函数总结下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

dp1--乘积最大

dp1--乘积最大 一、心得 1、用excel填数组很方便 2、 dp就是填表 找状态就是缩小规模 找状态转移方程就是 找状态的最后一次关系 二、题目 8782:乘积最大 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生...

【网络状态反馈码】

一些常见HTTP状态码为: 200 – 服务器成功返回网页 404 – 请求的网页不存在 503 – 服务不可用 常见HTTP状态码大全 1xx(临时响应) 表示临时响应并需要请求者继续执行操作的状态代码。 代码 说明 http状态码 100 (继续) 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。 http状态码...

IDEA中导入多个包自动合并为星号

  IDEA中导入同一个包下的几个class会自动合并为星号,如下图。可以通过设置让其不自动合并为星号。 1、选择File→Settings→Editor→Code style→Java,再点击右边的Imports,将Class count to use import with '*'的数量调高即可。 还可以设置一些规则: Names count to...

基于状态机的单片机按键短按长按功能的实现

转载自:http://m.elecfans.com/article/608499.html发表于 2017-12-28 08:43:46 控制/MCU +关注 1、引言 在自己在科研实践和对学生教学中发现,现在单片机学习中对于按键处理的方法都是:检测按键、延时消抖、按键执行、等待释放,整个按键处理的程序中大量出现“delay_1ms(5);”和“...

Delphi中API编程编译实现

Delphi作为一种面向对象的可视化开发工具以其开发程序的高速度和编译代码的高效率受到广大编程人员的青睐。尽管Delphi已经提供了非常强大的开发组件(VCL),但灵活使用API函数一定可以使你的程序增色不少。 一、状态键的检查 不少流行软件的编辑窗口(包括Delphi的代码编辑窗口)的底部都有一个状态条用来显示一些状态信息,比如当前光标的位置等。 通常键...

FPGA -- 实验一:闪烁灯(1)

  第一个实验就简单的实现一个灯闪烁的程序(主要也是为了回顾一下语法,仿真以及下载的流程)   基本思路是:利用计数器去计数0.5s,然后每隔0.5s改变以下LED输出引脚的电平状态   硬件电路如下:(与FPGA中的对应连接,在代码注释中给出)      1.在上次建立的那个设计文件里输入以下内容   (这个实验主要做一个演示,以后建工程等步骤不再赘述)...