一、入门案例
参考demo
- sunbufu的源码(主要还是参照这个大佬的源码和博客)
- sunbufu的博客
- qq
案例流程图如下所示,本案例源码
下面放置关键代码
OrderStateMachineConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| @Configuration @EnableStateMachine(name="orderStateMachine") public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderState, OrderEvent> { public OrderStateMachineConfig() {
}
@Override public void configure(StateMachineStateConfigurer<OrderState, OrderEvent> states) throws Exception { states.withStates() .initial(OrderState.WAIT_PAY) .states(EnumSet.allOf(OrderState.class)); }
@Override public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception { transitions .withExternal().source(OrderState.WAIT_PAY).target(OrderState.WAIT_DELIVER).event(OrderEvent.PAY) .and() .withExternal().source(OrderState.WAIT_DELIVER).target(OrderState.WAIT_RECEIVE).event(OrderEvent.DELIVER) .and() .withExternal().source(OrderState.WAIT_RECEIVE).target(OrderState.FINISH).event(OrderEvent.RECEIVE);
} }
|
OrderStateMachinePersisterConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Configuration public class OrderStateMachinePersisterConfig { @Bean public StateMachinePersister<OrderState, OrderEvent, Order> orderStateMachinePersist() { return new DefaultStateMachinePersister<>(new StateMachinePersist<OrderState, OrderEvent, Order>() { @Override public StateMachineContext<OrderState, OrderEvent> read(Order order) { return new DefaultStateMachineContext<>(order.getState(), null, null, null); }
@Override public void write(StateMachineContext<OrderState, OrderEvent> context, Order order) throws Exception { order.setState(context.getState()); } }); } }
|
OrderStateMachineHandler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Component public class OrderStateMachineHandler { @Autowired private StateMachine<OrderState, OrderEvent> stateMachine; @Autowired private StateMachinePersister<OrderState, OrderEvent, Order> stateMachinePersister;
public synchronized boolean sendEvent(OrderEvent event, Order order) { boolean result = false; try { stateMachine.start(); stateMachinePersister.restore(stateMachine, order); Message<OrderEvent> eventMessage = MessageBuilder.withPayload(event).setHeader("order", order).build(); result = stateMachine.sendEvent(eventMessage); stateMachinePersister.persist(stateMachine, order); } catch (Exception e) { e.printStackTrace(); } finally { stateMachine.stop(); } return result; } }
|
OrderStateMachineListener
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| @Component @WithStateMachine(name = "orderStateMachine") public class OrderStateMachineListener { private final static Logger log= LoggerFactory.getLogger(OrderStateMachineListener.class); @OnTransition(source = "WAIT_PAY", target = "WAIT_DELIVER") public boolean pay(Message<OrderEvent> message) { OrderEvent payload = message.getPayload(); String name = payload.name(); log.info("完成动作---"+name); return true; }
@OnTransition(source = "WAIT_DELIVER", target = "WAIT_RECEIVE") public boolean deliver(Message<OrderEvent> message) { OrderEvent payload = message.getPayload(); String name = payload.name(); log.info("完成动作---"+name); return true; }
@OnTransition(source = "WAIT_RECEIVE", target = "FINISH") public boolean receive(Message<OrderEvent> message) { OrderEvent payload = message.getPayload(); String name = payload.name(); log.info("完成动作---"+name); return true; } }
|
二、状态机
我理解的状态机的作用
- 在允许的不同状态间进行切换
- 防止在不允许的状态间切换导致的问题
Spring Statemachine各模块作用
模块 | 描述 |
---|
spring-statemachine-core | Spring 状态机的核心系统。 |
spring-statemachine-recipes-common | 不需要核心框架之外的依赖项的常见配方。 |
spring-statemachine-kryo | Spring Statemachine的Kryo序列化器 |
spring-statemachine-data-common | Spring Data的通用支持模块 |
spring-statemachine-data-jpa | Spring Data JPA的支持模块 |
spring-statemachine-data-redis | Spring Data Redis的支持模块 |
spring-statemachine-data-mongodb | Spring Data MongoDB的支持模块 |
spring-statemachine-zookeeper | 分布式状态机的 Zookeeper 集成 |
spring-statemachine-test | 状态机测试的支持模块 |
spring-statemachine-cluster | Spring Cloud Cluster 的支持模块。请注意,Spring Cloud Cluster 已被 Spring Integration 取代 |
spring-statemachine-uml | 使用 Eclipse Papyrus 进行 UI UML 建模的支持模块 |
spring-statemachine-autoconfigure | Spring Boot 的支持模块 |
spring-statemachine-bom | 材料清单pom |
spring-statemachine-starter | Spring Boot 启动器 |
2.1 需求
实现一个审批功能,时序图如下。
分为四个模块来完成,启动模块、公共模块、信息提供者和信息管理者。参照IDEA创建多模块SpringBoot项目
导入依赖,版本的选用可以参考官网doc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| <?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.3.1.RELEASE</version> <relativePath/> </parent> <groupId>top.meethigher.spring.statemachine.enhanced</groupId> <artifactId>spring-statemachine-enhanced</artifactId> <version>1.0</version> <name>spring-statemachine-enhanced</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-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
<dependency> <groupId>org.springframework.statemachine</groupId> <artifactId>spring-statemachine-core</artifactId> <version>2.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.statemachine</groupId> <artifactId>spring-statemachine-data-common</artifactId> <version>2.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.statemachine</groupId> <artifactId>spring-statemachine-kryo</artifactId> <version>2.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.statemachine</groupId> <artifactId>spring-statemachine-data-jpa</artifactId> <version>2.2.1.RELEASE</version> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
|