Эта статья была впервые опубликована на моем личном сайте:StateMachine в Spring Boot 2.x
Spring StateMachine — это фреймворк конечного автомата.В проекте Spring framework разработчики могут получить конечный бизнес-автомат с помощью простой настройки, без необходимости самостоятельно управлять определением, инициализацией и другими процессами конечного автомата. В сегодняшней статье мы используем пример, чтобы изучить использование среды Spring StateMachine.
Введение в дело
Предположим, в бизнес-системе есть такой объект, который имеет три состояния: черновик, ожидание выпуска и выпуск завершен.Бизнес-действия для этих трех состояний относительно просты, а именно: онлайн, выпуск и откат. Автомат бизнес-состояний показан на следующем рисунке.
настоящий бой
Затем выполняется демонстрация Spring StateMachine на основе приведенного выше бизнес-конечного автомата.
- Создайте базовый проект Spring Boot и добавьте зависимости Spring StateMachine в основной файл pom:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>online.javaadu</groupId>
<artifactId>statemachinedemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>statemachinedemo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--加入spring statemachine的依赖-->
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-core</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Определите перечисление состояний и перечисление событий, код выглядит следующим образом:
/**
* 状态枚举
**/
public enum States {
DRAFT,
PUBLISH_TODO,
PUBLISH_DONE,
}
/**
* 事件枚举
**/
public enum Events {
ONLINE,
PUBLISH,
ROLLBACK
}
- Завершите настройку конечного автомата, включая: (1) начальное состояние и все состояния конечного автомата; (2) правила перехода между состояниями.
@Configuration
@EnableStateMachine
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {
states.withStates().initial(States.DRAFT).states(EnumSet.allOf(States.class));
}
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {
transitions.withExternal()
.source(States.DRAFT).target(States.PUBLISH_TODO)
.event(Events.ONLINE)
.and()
.withExternal()
.source(States.PUBLISH_TODO).target(States.PUBLISH_DONE)
.event(Events.PUBLISH)
.and()
.withExternal()
.source(States.PUBLISH_DONE).target(States.DRAFT)
.event(Events.ROLLBACK);
}
}
- Определите тестовый бизнес-объект, и изменение состояния конечного автомата будет отражено в изменении состояния бизнес-объекта.
@WithStateMachine
@Data
@Slf4j
public class BizBean {
/**
* @see States
*/
private String status = States.DRAFT.name();
@OnTransition(target = "PUBLISH_TODO")
public void online() {
log.info("操作上线,待发布. target status:{}", States.PUBLISH_TODO.name());
setStatus(States.PUBLISH_TODO.name());
}
@OnTransition(target = "PUBLISH_DONE")
public void publish() {
log.info("操作发布,发布完成. target status:{}", States.PUBLISH_DONE.name());
setStatus(States.PUBLISH_DONE.name());
}
@OnTransition(target = "DRAFT")
public void rollback() {
log.info("操作回滚,回到草稿状态. target status:{}", States.DRAFT.name());
setStatus(States.DRAFT.name());
}
}
- Для написания тестовых случаев здесь мы используем вместо этого интерфейс CommandLineRunner, определяем StartupRunner, запускаем конечный автомат в методе run этого класса, отправляем различные события и проверяем поток конечного автомата через журнал.
public class StartupRunner implements CommandLineRunner {
@Resource
StateMachine<States, Events> stateMachine;
@Override
public void run(String... args) throws Exception {
stateMachine.start();
stateMachine.sendEvent(Events.ONLINE);
stateMachine.sendEvent(Events.PUBLISH);
stateMachine.sendEvent(Events.ROLLBACK);
}
}
После запуска вышеуказанной программы мы можем получить следующий вывод в консоли.Мы выполнили три операции: выход в сеть, публикация и откат.На рисунке ниже мы видим соответствующий лог. Однако я также обнаружил неожиданное место - при запуске конечного автомата также печатался лог - "Операция откатывается и возвращается в черновое состояние. целевой статус: ЧЕРНОВИК", это должна быть настройка конечного автомата. начальное состояние.
анализировать
Как показано в реальном боевом процессе выше, шаги по использованию Spring StateMachine следующие:
- Определить перечисление состояний и перечисление событий
- Определить начальное состояние и все состояния конечного автомата
- Определение правил перехода между состояниями
- Используйте конечные автоматы в бизнес-объектах и напишите методы прослушивания, которые реагируют на изменения состояния.
Для унифицированного управления операциями изменения состояния мы рассмотрим введение в проект конечного автомата, чтобы другие бизнес-модули были изолированы от модуля передачи состояния, а другие бизнес-модули не были запутаны в текущем состоянии. то, что должно быть сделано. При применении конечного автомата для достижения бизнес-требований ключевым моментом является анализ бизнес-состояния.Если конечный автомат хорошо спроектирован, вы можете использовать Spring StateMachine для конкретной реализации или реализовать конечный автомат самостоятельно.
Преимущество использования Spring StateMachine заключается в том, что вам не нужно заботиться о деталях реализации конечного автомата, вам нужно только заботиться о том, в каком состоянии находится бизнес, каковы правила передачи между ними и бизнес-операции, которые выполняются. действительно будет выполняться после передачи каждого состояния.
Полный пример этой статьи см.GitHub.com/Grumbling CA UC/SP…
использованная литература
В этом выпуске основное внимание уделяется таким темам, как серверные технологии, устранение неполадок и оптимизация JVM, вопросы на собеседованиях по Java, личностный рост и самоуправление, а читателям предлагается опыт работы и роста передовых разработчиков. .