Spring系列学习之Spring Statemachine状态机

英文原文:https://projects.spring.io/spring-statemachine/

目录

快速开始

Builder

JavaConfig

版本

资源

实战


Spring Statemachine是应用程序开发人员在Spring应用程序中使用状态机概念的框架。

Spring Statemachine旨在提供以下功能:

  •     易于使用的扁平单级状态机,用于简单的使用案例。
  •     分层状态机结构,以简化复杂的状态配置。
  •     状态机区域提供更复杂的状态配置。
  •     使用触发器,转换,警卫和操作。
  •     键入安全配置适配器。
  •     生成器模式,用于在Spring Application上下文之外使用的简单实例化
  •     通常用例的食谱
  •     基于Zookeeper的分布式状态机
  •     状态机事件监听器。
  •     UML Eclipse Papyrus建模。
  •     将计算机配置存储在永久存储中。
  •     Spring IOC集成将bean与状态机关联起来。


状态机功能强大,因为行为始终保证一致,使调试相对容易。这是因为操作规则是在机器启动时写成的。这个想法是你的应用程序可能存在于有限数量的状态中,某些预定义的触发器可以将你的应用程序从一个状态转移到另一个状态。此类触发器可以基于事件或计时器。

在应用程序之外定义高级逻辑然后依靠状态机来管理状态要容易得多。您可以通过发送事件,侦听更改或仅请求当前状态来与状态机进行交互。

你想问一个问题吗?转到StackOverflow并使用标签spring-statemachineGitter

快速开始

在项目中使用spring-statemachine的推荐方法是使用依赖关系管理系统 - 下面的代码片段可以复制并粘贴到您的构建中。 需要帮忙? 请参阅我们的Maven和Gradle构建入门指南。(导航到英文页面可以选择版本和依赖方式)

Maven

<dependencies>
    <dependency>
        <groupId>org.springframework.statemachine</groupId>
        <artifactId>spring-statemachine-core</artifactId>
        <version>2.0.3.RELEASE</version>
    </dependency>
</dependencies>

Gradle

dependencies {
    compile 'org.springframework.statemachine:spring-statemachine-core:2.0.3.RELEASE'
}

以下示例应该了解如何配置和使用状态机。 假设我们有状态STATE1,STATE2和事件EVENT1,EVENT2。

static enum States {
    STATE1, STATE2
}

static enum Events {
    EVENT1, EVENT2
}

 

Builder

public StateMachine<States, Events> buildMachine() throws Exception {
    Builder<States, Events> builder = StateMachineBuilder.builder();

    builder.configureStates()
        .withStates()
            .initial(States.STATE1)
            .states(EnumSet.allOf(States.class));

    builder.configureTransitions()
        .withExternal()
            .source(States.STATE1).target(States.STATE2)
            .event(Events.EVENT1)
            .and()
        .withExternal()
            .source(States.STATE2).target(States.STATE1)
            .event(Events.EVENT2);

    return builder.build();
}
StateMachine<States, Events> stateMachine = buildMachine();
stateMachine.start();
stateMachine.sendEvent(Events.EVENT1);
stateMachine.sendEvent(Events.EVENT2);

JavaConfig

@Configuration
@EnableStateMachine
static class Config1 extends EnumStateMachineConfigurerAdapter<States, Events> {

    @Override
    public void configure(StateMachineStateConfigurer<States, Events> states)
            throws Exception {
        states
            .withStates()
                .initial(States.STATE1)
                .states(EnumSet.allOf(States.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
            throws Exception {
        transitions
            .withExternal()
                .source(States.STATE1).target(States.STATE2)
                .event(Events.EVENT1)
                .and()
            .withExternal()
                .source(States.STATE2).target(States.STATE1)
                .event(Events.EVENT2);
    }
}
@WithStateMachine
static class MyBean {

    @OnTransition(target = "STATE1")
    void toState1() {
    }

    @OnTransition(target = "STATE2")
    void toState2() {
    }
}
static class MyApp {

    @Autowired
    StateMachine<States, Events> stateMachine;

    void doSignals() {
        stateMachine.start();
        stateMachine.sendEvent(Events.EVENT1);
        stateMachine.sendEvent(Events.EVENT2);
    }
}

 

版本

Spring Statemachine

Release

Documentation

2.1.0 M1

Reference API

2.1.0

Reference API

2.0.4

Reference API

2.0.3

Reference API

1.2.13

Reference API

1.2.12

Reference API

1.1.1

Reference API

资源

https://github.com/spring-projects/spring-statemachine/tree/master/spring-statemachine-samples

实战

封装消息数据:

package com.patrol.position;

import com.patrol.beans.user.UserPosition;
import com.patrol.position.stateMachine.Events;
import com.patrol.position.stateMachine.States;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.statemachine.StateMachine;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * 开启异步请求
 */
@EnableAsync
/**
 * 开启接口缓存
 */
@EnableCaching
/**
 * 开启定时任务调度
 */
@EnableScheduling
/**
 * 开启接口文档描述
 */
@EnableSwagger2
/**
 * @SpringBootApplication
 * <p>相当于@Configuration,@EnableAutoConfiguration和 @ComponentScan </p>
 */
@SpringBootApplication
public class PatrolPositionServiceApplication implements CommandLineRunner {

    @Autowired
    StateMachine<States, Events> stateMachine;

    @Override
    public void run(String... args) throws Exception {
        stateMachine.start();
        // 发送上线位置数据
        UserPosition userPosition = new UserPosition();
        userPosition.setUserId("123434");
        userPosition.setLive(true);
        userPosition.setPosition(new Double[]{103.2342343,31.23894343});
        Message userPositionMessage = MessageBuilder.withPayload(Events.ONLINE).setHeader("position",userPosition).build();
        stateMachine.sendEvent(userPositionMessage);
        // 发送离线位置数据
        userPosition = new UserPosition();
        userPositionMessage = MessageBuilder.withPayload(Events.OFFLINE).setHeader("position",userPosition).build();
        stateMachine.sendEvent(userPositionMessage);
    }

    public static void main(String[] args) {
        SpringApplication.run(PatrolPositionServiceApplication.class, args);
    }

}

消息监听处理:

package com.patrol.position.stateMachine;

import com.alibaba.fastjson.JSON;
import com.patrol.beans.user.UserPosition;
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;

/**
 * @Copyright: 2019-2021
 * @FileName: UserStateMachineService.java
 * @Author: PJL
 * @Date: 2021/1/25 17:40
 * @Description: 用户状态机监听
 */
@Slf4j
@WithStateMachine
public class StateMachineListener {

    /**
     * 获取业务数据
     * @param message
     * @return
     */
    private UserPosition getUserPosition( Message message){
        if(null == message|| null == message.getHeaders()){
            return null;
        }
        return (UserPosition)message.getHeaders().get("position");
    }

    /**
     * 用户在线
     * @param stateMachine
     * @param message
     */
    @OnTransition(target = "ONLINE")
    public void userOnline(StateMachine<States,Events> stateMachine, Message message) {
        log.info("用户状态机:======用户上线!======{}",stateMachine);
        UserPosition userPosition = this.getUserPosition(message);
        log.info("上线传入位置:" + JSON.toJSONString(userPosition));
    }

    /**
     * 用户离线
     * @param stateMachine
     * @param message
     */
    @OnTransition(target = "OFFLINE")
    public void userOffline(StateMachine<States,Events> stateMachine,  Message message) {
        log.info("用户状态机:======用户下线!======{}",stateMachine);
        UserPosition userPosition = this.getUserPosition(message);
        log.info("下线传入位置:" + JSON.toJSONString(userPosition));
    }
}

效果输出:

2021-01-26 10:56:46.731 [restartedMain] INFO  c.p.p.PatrolPositionServiceApplication | Started PatrolPositionServiceApplication in 32.654 seconds (JVM running for 37.851)
2021-01-26 10:56:46.841 [restartedMain] INFO  c.p.p.s.StateMachineListener | 用户状态机:======用户下线!======OFFLINE ONLINE  /  / uuid=c32e1ba9-7fa4-49a4-8fed-74cd40f0ac46 / id=null
2021-01-26 10:56:46.842 [restartedMain] INFO  c.p.p.s.StateMachineListener | 下线传入位置:null
2021-01-26 10:56:46.854 [restartedMain] INFO  o.s.s.s.LifecycleObjectSupport | started org.springframework.statemachine.support.DefaultStateMachineExecutor@7ad0542f
2021-01-26 10:56:46.855 [restartedMain] INFO  o.s.s.s.LifecycleObjectSupport | started OFFLINE ONLINE  / OFFLINE / uuid=c32e1ba9-7fa4-49a4-8fed-74cd40f0ac46 / id=null
2021-01-26 10:56:46.869 [restartedMain] INFO  c.p.p.s.StateMachineListener | 用户状态机:======用户上线!======OFFLINE ONLINE  / OFFLINE / uuid=c32e1ba9-7fa4-49a4-8fed-74cd40f0ac46 / id=null
2021-01-26 10:56:46.930 [restartedMain] INFO  c.p.p.s.StateMachineListener | 上线传入位置:{"distance":0.0,"live":true,"position":[103.2342343,31.23894343],"status":0,"time":0,"timestamp":0,"userId":"123434"}
2021-01-26 10:56:46.933 [restartedMain] INFO  c.p.p.s.StateMachineListener | 用户状态机:======用户下线!======OFFLINE ONLINE  / ONLINE / uuid=c32e1ba9-7fa4-49a4-8fed-74cd40f0ac46 / id=null
2021-01-26 10:56:46.933 [restartedMain] INFO  c.p.p.s.StateMachineListener | 下线传入位置:{"distance":0.0,"live":false,"status":0,"time":0,"timestamp":0}

参考文章:https://www.jianshu.com/p/c1d5fabaf818

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值