加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

SpringBoot-6-statemachine使用guard,action和@Ontransition

(2017-04-15 08:53:25)
分类: 微服务
接前文http://blog.sina.com.cn/s/blog_7d1968e20102wvm7.html
如果我们想在状态机转换前进行判断,如果判断成功则进行跳转,否则可以跳转到其他状态,那么我们就需要guard的帮助。guard可以返回true或false,如果返回true那么就被actionListener监听进入action(如果定义了的话),再然后进入@WithstateMachine的@Ontransition注解的方法。guard返回false就不会进入指定状态,但在false之前可以指定进入其他状态
即流程如下:状态转变触发(trigger)->状态机启动并加载配置->guard->action->onTransition->变成新状态
下面就是例子:

1.在状态机配置中指定guard和action

1)Builder1。
关键:guard和action也可以定义成纯方法,而不是spring bean。定义成bean的好处就是可以被其他Builder使用。
通过extendedState获取创建状态机时传递的参数:stateContext.getExtendedState().get(Student.class, Student.class);


 
@Component
public class Builder1 implements Builder{
    @Override
    public States getName(){
        return States.STATE1;
    }

    @Override
    public StateMachine<States, Events> build(BeanFactory beanFactory) throws Exception{
        StateMachineBuilder.Builder<States, Events> builder = StateMachineBuilder.builder();
        builder.configureConfiguration().withConfiguration().machineId("state1").autoStartup(true).beanFactory(beanFactory);
        builder.configureStates().withStates().initial(States.STATE1).states(EnumSet.allOf(States.class));
        builder.configureTransitions().withExternal().source(States.STATE1).target(States.STATE2).event(Events.EVENT_A)
                .guard(guardBuilder11To2()).action(actionBuilder11To2())
                .and().withExternal().source(States.STATE2).target(States.STATE2).event(Events.EVENT_B);
        return builder.build();
    }

    @Bean
    public Guard<States, Events> guardBuilder11To2() {
        return new Guard<States, Events>() {
            @Override
            public boolean evaluate(StateContext<States, Events> stateContext) {
                Student student = stateContext.getExtendedState().get(Student.class, Student.class);
                if(student.getId() != 1) {
                    System.out.println("builder1校验成功");
                    return true;
                }
                System.out.println("builder1校验不能跳转到2");
                return false;
            }
        };
    }
注意:
guard可以返回true或false,如果返回true那么就被actionListener监听进入action(如果定义了的话)guard返回false就不会跳转指定状态,但在false之前可以指定进入其他状态

    @Bean
    public Action<States, Events> actionBuilder11To2() {
        return new Action<States, Events>() {
            @Override
            public void execute(StateContext<States, Events> stateContext) {
                System.out.println("builder2的action成功跳转到2");
            }
        };
    }
}

2)Builder2。使用了builder1中的bean:actionBuilder11To2 

@Component
public class Builder2 implements Builder{
//    @Autowired
//    @Qualifier("actionBuilder11To2")
    @Resource(name = "actionBuilder11To2")
    private Action<States, Events> actionBuilder11To2;

    @Override
    public States getName(){
        return States.STATE2;
    }

    @Override
    public StateMachine<States, Events> build(BeanFactory beanFactory) throws Exception{
        StateMachineBuilder.Builder<States, Events> builder = StateMachineBuilder.builder();
        builder.configureConfiguration().withConfiguration().machineId("state2").autoStartup(true).beanFactory(beanFactory);
        builder.configureStates().withStates().initial(States.STATE2).states(EnumSet.allOf(States.class));
        builder.configureTransitions().withExternal().source(States.STATE2).target(States.STATE3).event(Events.EVENT_B)
        .guard(guardBuilder22To3()).action(actionBuilder11To2);
        return builder.build();
    }

    @Bean
    public Guard<States, Events> guardBuilder22To3() {
        return new Guard<States, Events>() {
            @Override
            public boolean evaluate(StateContext<States, Events> stateContext) {
                Student student = stateContext.getExtendedState().get(Student.class, Student.class);
                if(student.getId() == 1) {
                    System.out.println("校验成功");
                    return true;
                }
                return false;
            }
        };
    }

    @Bean
    public Action<States, Events> actionBuilder22To3() {
        return new Action<States, Events>() {
            @Override
            public void execute(StateContext<States, Events> stateContext) {
                System.out.println("action成功跳转到3");
            }
        };
    }
}

2.BuilderFactory
提供了create方法,使用 stateMachine.getExtendedState().getVariables().put进行传递附加参数。

@Component
public class BuildFactory implements InitializingBean {
    @Autowired
    private BeanFactory beanFactory;

    @Autowired
    private List<Builder> builders;

    private Map<States, Builder> statesStateMachineMap = new ConcurrentHashMap<>();

    public void run(States state, Events event) throws Exception{
        Builder builder = statesStateMachineMap.get(state);
        StateMachine<States, Events> stateMachine = builder.build(beanFactory);
        stateMachine.sendEvent(event);
    }

    public  StateMachine<States, Events> create(States state) throws Exception{
        Builder builder = statesStateMachineMap.get(state);
        StateMachine<States, Events> stateMachine = builder.build(beanFactory);
        stateMachine.getExtendedState().getVariables().put(Student.class, new Student(1, "haha"));
        return stateMachine;
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        statesStateMachineMap = builders.stream().collect(Collectors.toMap(Builder::getName, Function.identity()));
    }
}


3.@WithStateMachine中的Ontransition中定义的方法

1)Builder2Transition :方法中含有参数StateContext<States, Events> context可以获取状态机传递的参数
@WithStateMachine(name = "state2")
public class Builder2Transition {
    @OnTransition(target = "STATE2")
    public void init(StateContext<States, Events> context) {
        Pupil s = new Pupil(12, "Bill", "piano");
        System.out.println("Init to state1:" + s.getName()+ ":" + s.getId() + ":" + s.getHobbies());
    }

    @OnTransition(target = "STATE3", source = "STATE2")
    public void tansFrom2To3(StateContext<States, Events> context) {
        Student student = context.getExtendedState().get(Student.class, Student.class);
        System.out.println("Transiform from 2 to 3 ," + student.getId() + "---" + student.getName());
    }
}

2)Builder1Transition
 @WithStateMachine(name = "state1")
public class Builder1Transition {
    @OnTransition(target = "STATE1")
    public void init() {
        Pupil s = new Pupil(12, "Bill", "piano");
        System.out.println("Init to state1:" + s.getName()+ ":" + s.getId() + ":" + s.getHobbies());
    }

    @OnTransition(target = "STATE2", source = "STATE1")
    public void tansFrom1To2() {
        System.out.println("Transiform from 1 to 2");
    }

    @OnTransition(target = "STATE3", source = "STATE2")
    public void tansFrom2To3() {
        System.out.println("Transiform from 2 to 3");
    }

    @OnTransition(target = "STATE2", source = "STATE2")
    public void tansFrom12o2() {
        System.out.println("Transiform from 2 to 2");
    }
}

4.测试
@Test
public void TestBuilder1() throws Exception{
StateMachine<States, Events> machine1 = buildFactory.create(States.STATE1);
machine1.sendEvent(Events.EVENT_A);

StateMachine<States, Events> machine2 = buildFactory.create(States.STATE2);
machine2.sendEvent(Events.EVENT_B);
}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有