springstatemachine多个状态机实践
最近在做老系统升级改造,为了解决原来流程复杂,代码冗杂的情况,计划引入状态机框架来改造,为更好理解,也为记录下自己的学习过程,计划写总结博文。
状态机spring statemachine 概述
Spring Statemachine是应用程序开发人员在Spring应用程序中使用状态机概念的框架
Spring Statemachine旨在提供以下功能:
1. 易于使用的扁平单级状态机,用于简单的使用案例。
2. 分层状态机结构,以简化复杂的状态配置。
3. 状态机区域提供更复杂的状态配置。
4. 使用触发器,转换,警卫和操作。
5. 键入安全配置适配器。
6. 生成器模式,用于在Spring Application上下文之外使用的简单实例化通常用例的食谱
7. 基于Zookeeper的分布式状态机
8. 状态机事件监听器。
9. UML Eclipse Papyrus建模。
10. 将计算机配置存储在永久存储中。
11. Spring IOC集成将bean与状态机关联起来。
状态机功能强大,因为行为始终保证一致,使调试相对容易。这是因为操作规则是在机器启动时写成的。这个想法是你的应用程序可能存在于有限数量的状态中,某些预定义的触发器可以将你的应用程序从一个状态转移到另一个状态。此类触发器可以基于事件或计时器。
在应用程序之外定义高级逻辑然后依靠状态机来管理状态要容易得多。您可以通过发送事件,侦听更改或仅请求当前状态来与状态机进行交互。
快速开始
已经写过状态机的简单启动,状态流转的例子,但实际应用过程不可能只用到一个machine,需多个machine处理对象流转。
下面的实践有以下特色:
1、不同线程启用不同statemachine实例处理
2、用工厂模式创建statemachine,且用StateMachinePersist根据recruit对象不同状态反序列化statemachine
3、 用message 给OnTransition注解的方法传递对象
@Configuration
//@EnableStateMachine(name = "ddd")
@Scope("prototype")
@EnableStateMachineFactory(name = "recruitStateMachineFactory")
public class Config1 extends EnumStateMachineConfigurerAdapter<States, Events> {
/**订单状态机ID*/
public static final String orderStateMachineId = "recruitStateMachineId";
@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)
}
@Bean
public StateMachinePersister<States, Events, Recruit> persister(){
return new DefaultStateMachinePersister<States, Events, Recruit>(new StateMachinePersist<States, Events, Recruit>() {
@Override
public void write(StateMachineContext<States, Events> context, Recruit order) throws Exception {
//此处并没有进行持久化操作
//order.setStatus(context.getState());
}
@Override
public StateMachineContext<States, Events> read(Recruit order) throws Exception {
//此处直接获取order中的状态,其实并没有进行持久化读取操作
StateMachineContext<States, Events> result =new DefaultStateMachineContext<States, Events>(order.getStates(), null, null, null, null, orderStateMachineId);
return result;
}
});
}
}
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
状态转换
@WithStateMachine(name = "recruitStateMachineId")
public class MyBean {
@OnTransition(source="STATE2" ,target = "STATE1")
public void toState1(Message message) {
Recruit recruit = (Recruit) message.getHeaders().get("recruit");
System.out.println("toState1" +Thread.currentThread().toString());
}
@OnTransition(source="" ,target = "STATE1")
public void initState() {
System.out.println("toState1"+Thread.currentThread().toString());
}
@OnTransition(source="STATE1",target = "STATE2")
public void toState2() throws Exception {
System.out.println("toState2"+Thread.currentThread().toString());
//throw new Exception();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@RestController
public class MyApp {
ThreadLocal<StateMachine> stateMachineThreadLocal = new ThreadLocal<StateMachine>();
@Autowired
@Qualifier("recruitStateMachineFactory" )
StateMachineFactory<States, Events> stateMachineFactory;
@Autowired
private StateMachinePersister<States, Events,Recruit> persister;
@RequestMapping("/hello")
void doSignals() {
System.out.println("start before");
Recruit recruit = new Recruit();
StateMachine stateMachinet = getStateMachine(recruit);
System.out.println("dosignals stateMachinet hashcode "+stateMachinet.hashCode()+" recruit hashcode is "+recruit.hashCode());
stateMachinet.sendEvent(Events.EVENT1);
stateMachinet.sendEvent(Events.EVENT2);
}
private StateMachine getStateMachine(Recruit recruit){
StateMachine machine = stateMachineThreadLocal.get();
if (null == machine){
machine = stateMachineFactory.getStateMachine("recruitStateMachineId");
}
try {
machine.start();
persister.restore(machine,recruit);
} catch (Exception e) {
//e.printStackTrace();
}
return machine;
}
void sendEvent(Events events,Recruit recruit){
Message message = MessageBuilder.withPayload(events).setHeader("recruit", recruit).build();
StateMachine stateMachine = getStateMachine(recruit);
stateMachine.sendEvent(message);
}
@RequestMapping("/sendEvent1")
void sendEvent(){
Recruit recruit = new Recruit();
recruit.setStates(States.STATE1);
StateMachine stateMachine = getStateMachine(recruit);
stateMachine.sendEvent(Events.EVENT1);
}
@RequestMapping("/sendEvent2")
void sendEvent2(){
Recruit recruit = new Recruit();
recruit.setStates(States.STATE2);
StateMachine stateMachine = getStateMachine(recruit);
stateMachine.sendEvent(Events.EVENT2);
}
}
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
总结
解决了如何处理多用户多对象场景如何启用状态机的例子,但只有状态机简单的状态迁移,状态机配置可以有多种方法,下一篇文章分析各种配置的不同用法
ChoiceTransitionConfigurer<S,E> withChoice()
ChoiceTransitionConfigurer<S,E> withChoice()
EntryTransitionConfigurer<S,E> withEntry()
ExitTransitionConfigurer<S,E> withExit()
ExternalTransitionConfigurer<S,E> withExternal()
ForkTransitionConfigurer<S,E> withFork()
HistoryTransitionConfigurer<S,E> withHistory()
InternalTransitionConfigurer<S,E> withInternal()
JoinTransitionConfigurer<S,E> withJoin()
JunctionTransitionConfigurer<S,E> withJunction()
LocalTransitionConfigurer<S,E> withLocal()
————————————————
版权声明:本文为CSDN博主「chenpei1990」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/chenpei1990/java/article/details/81636897
以上是 springstatemachine多个状态机实践 的全部内容, 来源链接: utcz.com/z/515729.html