zoukankan      html  css  js  c++  java
  • Squirrel(松鼠)状态机的使用

    概述

    其实对于英文好的同学来说,这个状态机的使用就非常简单了,参考https://github.com/hekailiang/squirrel上的文档即可,因为这个状态机的入门成本并不高。

    实战代码

    由于这个状态机比较简单,就直接上代码了,注释写在代码里,通过调试运行,相信你马上就理解了。

    定义事件FSMEvent.java

    /**
     * 定义状态机事件
     *
     * @author: 吴庆龙
     * @date: 2019/12/23 10:44 上午
     */
    public enum FSMEvent {
        ToA, ToB, ToC, ToD, toE, ToF
    }
    

    定义监听器DeclarativeEventListener.java

    import lombok.extern.slf4j.Slf4j;
    import org.squirrelframework.foundation.exception.TransitionException;
    import org.squirrelframework.foundation.fsm.Action;
    import org.squirrelframework.foundation.fsm.annotation.*;
    
    /**
     * 声明式监听
     *
     * @author: 吴庆龙
     * @date: 2019/12/23 1:20 下午
     */
    @Slf4j
    public class DeclarativeEventListener {
    
        /**
         * 转换事件开始时进行调用
         */
        @OnTransitionBegin
        public void transitionBegin(FSMEvent event) {
            System.out.println();
            log.info("transitionBegin event {}", event);
        }
    
        /**
         * 转换事件开始时进行调用
         * 可以加入条件
         * 'event'(E), 'from'(S), 'to'(S), 'context'(C) and 'stateMachine'(T) can be used in MVEL scripts
         */
        @OnTransitionBegin(when="event.name().equals("ToB")")
        public void transitionBeginConditional() {
            log.info("transitionBeginConditional");
        }
    
        /**
         * 转换事件结束时进行调用
         * 这个方法必须是 public 并且返回值是 void
         */
        @OnTransitionEnd
        @ListenerOrder(10)
        public void transitionEnd() {
            log.info("transitionEnd");
            System.out.println();
        }
    
        @OnTransitionComplete
        public void transitionComplete(String from, String to, FSMEvent event, Integer context) {
            log.info("transitionComplete {}=>{} on {} with {}", from, to, event, context);
        }
    
        @OnTransitionException
        public void transitionException(String from, String to, FSMEvent event, Integer context) {
            log.info("transitionException");
        }
    
        /**
         * 当转换被拒绝时,将调用注有TransitionDecline的方法
         */
        @OnTransitionDecline
        public void transitionDeclined(String from, FSMEvent event, Integer context) {
            log.info("transitionDeclined {}=>??? on {} with {}", from, event, context);
        }
    
        /**
         * 带有 OnAfterActionExecuted 注释的方法将在调用操作之前被调用
         * 实际是 callMethod 中的方法被调用钱执行这个方法。类似于 AOP 的效果,运行一下即可知道
         */
        @OnBeforeActionExecuted
        public void onBeforeActionExecuted(Object sourceState, Object targetState,
                                           Object event, Object context, int[] mOfN, Action<?, ?, ?,?> action) {
            log.info("onBeforeActionExecuted");
        }
    
        /**
         * 带有 OnAfterActionExecuted 注释的方法将在调用操作之后被调用
         * 实际是 callMethod 中的方法被调用后执行这个方法。类似于 AOP 的效果,运行一下即可知道
         */
        @OnAfterActionExecuted
        public void onAfterActionExecuted(Object sourceState, Object targetState,
                                          Object event, Object context, int[] mOfN, Action<?, ?, ?,?> action) {
            log.info("onAfterActionExecuted");
        }
    
        /**
         * 带有 OnActionExecException 注释的方法将在调用操作异常之后被调用
         * 实际是 callMethod 中的方法被调用时抛异常了之后执行这个方法。类似于 AOP 的效果,运行一下即可知道
         */
        @OnActionExecException
        public void onActionExecException(Action<?, ?, ?,?> action, TransitionException e) {
            log.info("onActionExecException");
        }
    
    }
    

    状态机和StateMachineSample.java

    import lombok.extern.slf4j.Slf4j;
    import org.squirrelframework.foundation.fsm.*;
    import org.squirrelframework.foundation.fsm.annotation.StateMachineParameters;
    import org.squirrelframework.foundation.fsm.impl.AbstractUntypedStateMachine;
    
    /**
     * 定义状态机,支持如下格式的方法定义
     * transitFrom[fromStateName]To[toStateName]On[eventName]When[conditionName]
     * transitFrom[fromStateName]To[toStateName]On[eventName]
     * transitFromAnyTo[toStateName]On[eventName]
     * transitFrom[fromStateName]ToAnyOn[eventName]
     * transitFrom[fromStateName]To[toStateName]
     * on[eventName]
     * entry[eventName]
     * exit[eventName]
     *
     * @author: 吴庆龙
     * @date: 2019/12/23 10:46 上午
     */
    @Slf4j
    @StateMachineParameters(stateType = String.class, eventType = FSMEvent.class, contextType = Integer.class)
    public class StateMachineSample extends AbstractUntypedStateMachine {
    
        // =========== A -> B:需要将方法名配置在 callMethod 内
        public void fromAToB(String from, String to, FSMEvent event, Integer context) {
            log.info("转换事件 {}=>{} on {} with {}.", from, to, event, context);
        }
    
        // =========== B -> C:符合 transitFrom[fromStateName]To[toStateName] 格式,不需要配置 callMethod
        public void transitFromBToC(String from, String to, FSMEvent event, Integer context) {
            log.info("转换事件 {}=>{} on {} with {}.", from, to, event, context);
        }
    
        // =========== 进入 A, 符合 entry[StateName] 格式,不需要配置 callMethod
        public void entryA(String from, String to, FSMEvent event, Integer context) {
            log.info("进入事件 {}=>{} on {} with {}.", from, to, event, context);
        }
    
        // =========== 退出 A, 符合 exit[StateName] 格式,不需要配置 callMethod
        public void exitA(String from, String to, FSMEvent event, Integer context) {
            log.info("退出事件 {}=>{} on {} with {}.", from, to, event, context);
        }
    
        // =========== 进入 B
        public void enterB(String from, String to, FSMEvent event, Integer context) {
            log.info("进入事件 {}=>{} on {} with {}.", from, to, event, context);
        }
    
        // =========== 退出 B
        public void exitB(String from, String to, FSMEvent event, Integer context) {
            log.info("退出事件 {}=>{} on {} with {}.", from, to, event, context);
        }
    
        // ==========================================================================================
        // 如果不想用 DeclarativeEventListener 这种声明在单独类里的方法,可以直接重写以下方法,效果是一样的
        // 两者同时用也可以,为了代码方便最好别这样
        // ==========================================================================================
        @Override
        protected void afterTransitionCausedException(Object fromState, Object toState, Object event, Object context) {
    //        super.afterTransitionCausedException(fromState, toState, event, context);
            // 默认的实现是直接抛异常
            log.info("Override 发生错误 {}", getLastException().getMessage());
        }
        @Override
        protected void beforeTransitionBegin(Object fromState, Object event, Object context) {
            // 转换开始时被调用
            System.out.println();
            super.beforeTransitionBegin(fromState, event, context);
            log.info("Override beforeTransitionBegin");
        }
        @Override
        protected void afterTransitionCompleted(Object fromState, Object toState, Object event, Object context) {
            // 转换完成时被调用
            super.afterTransitionCompleted(fromState, toState, event, context);
            log.info("Override afterTransitionCompleted");
        }
        @Override
        protected void afterTransitionEnd(Object fromState, Object toState, Object event, Object context) {
            // 转换结束时被调用
            super.afterTransitionEnd(fromState, toState, event, context);
            log.info("Override afterTransitionEnd");
            System.out.println();
        }
        @Override
        protected void afterTransitionDeclined(Object fromState, Object event, Object context) {
            // 当转换被拒绝时被调用。实际是调用 callMethod 中的方法被调用时,抛出异常时被调用
            super.afterTransitionDeclined(fromState, event, context);
            log.info("Override afterTransitionDeclined");
        }
        @Override
        protected void beforeActionInvoked(Object fromState, Object toState, Object event, Object context) {
            // 当转换开始时被调用。实际是 callMethod 中的方法被调用时,类似于 AOP 的效果,运行一下即可知道
            super.beforeActionInvoked(fromState, toState, event, context);
            log.info("Override beforeActionInvoked");
        }
        @Override
        protected void afterActionInvoked(Object fromState, Object toState, Object event, Object context) {
            // 当转换结束时被调用。实际是 callMethod 被调用时,类似于 AOP 的效果,运行一下即可知道
            super.afterActionInvoked(fromState, toState, event, context);
            log.info("Override afterActionInvoked");
        }
    
    
        public static void main(String[] args) {
            // 构造 builder
            StateMachineConfiguration stateMachineConfiguration = StateMachineConfiguration.create()
                    .enableAutoStart(false);
            UntypedStateMachineBuilder builder = StateMachineBuilderFactory.create(StateMachineSample.class);
            builder.setStateMachineConfiguration(stateMachineConfiguration);
    
            // 配置状态流转时触发的事件
            builder.externalTransition().from("A").to("B").on(FSMEvent.ToB).callMethod("fromAToB");
            builder.externalTransition().from("B").to("C").on(FSMEvent.ToC);
            builder.onEntry("A");
            builder.onExit("A");
            builder.onEntry("B").callMethod("enterB");
            builder.onExit("B");
    
            // 使用状态机
            UntypedStateMachine fsm = builder.newStateMachine("A");
            fsm.start();
    
            // 添加监听器
    //        fsm.addStateMachineListener(new StateMachineListener<UntypedStateMachine, Object, Object, Object>() {
    //            @Override
    //            public void stateMachineEvent(StateMachineEvent<UntypedStateMachine, Object, Object, Object> event) {
    //                log.info("lastState: " + event.getStateMachine().getLastState());
    //            }
    //        });
    //        fsm.addDeclarativeListener(new DeclarativeEventListener());
            // 源码中的日志 demo
    //        StateMachineLogger logger = new StateMachineLogger(fsm);
    //        logger.startLogging();
    
            fsm.fire(FSMEvent.ToB, 1);
            fsm.fire(FSMEvent.ToC);
    
            System.out.println("Current state is " + fsm.getCurrentState());
        }
    
    }
    
  • 相关阅读:
    三:oracle练习
    二:SQL 函数
    一:SQL基本语法
    生产者与消费者模式(理解) 进程间通信之消息队列编程
    C语言
    前端面试:基础javascript篇(二)
    Koa入门和源码分析
    前端面试:基础javascript篇(一)
    前端面试题(二)
    C复习
  • 原文地址:https://www.cnblogs.com/wuqinglong/p/12123121.html
Copyright © 2011-2022 走看看