SpringStateMachine结合UML
springStateMachine2.X开始支持与UML结合,大大方便了对其的应用,在1.X的版本中大量繁杂的定义状态、action等等内容都得到了很好的解决;
step1 eclipse安装Papyrus插件
安装完成后:
官方说明:https://docs.spring.io/spring-statemachine/docs/2.0.4.RELEASE/reference/htmlsingle/
Defining a state machine configuration with UI modeling is supported via Eclipse Papyrus framework.
From eclipse wizard create a new Papyrus Model with UML Diagram Language. In this example it’s named as simple-machine. Then you’ve given an option to choose various diagram kind’s and a StateMachine Diagram must be chosen.
We want to create a machine having two states, S1 and S2 where S1 is initial state. Then event E1 is created to do a transition from S1 to S2. In papyrus a machine would then look like something shown below.
<?xml version="1.0" encoding="UTF-8"?>
<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_AMP3IP8fEeW45bORGB4c_A" name="RootElement">
<packagedElement xmi:type="uml:StateMachine" xmi:id="_AMRFQP8fEeW45bORGB4c_A" name="StateMachine">
<region xmi:type="uml:Region" xmi:id="_AMRsUP8fEeW45bORGB4c_A" name="Region1">
<transition xmi:type="uml:Transition" xmi:id="_chgcgP8fEeW45bORGB4c_A" source="_EZrg4P8fEeW45bORGB4c_A" target="_FAvg4P8fEeW45bORGB4c_A">
<trigger xmi:type="uml:Trigger" xmi:id="_hs5jUP8fEeW45bORGB4c_A" event="_NeH84P8fEeW45bORGB4c_A"/>
</transition>
<transition xmi:type="uml:Transition" xmi:id="_egLIoP8fEeW45bORGB4c_A" source="_Fg0IEP8fEeW45bORGB4c_A" target="_EZrg4P8fEeW45bORGB4c_A"/>
<subvertex xmi:type="uml:State" xmi:id="_EZrg4P8fEeW45bORGB4c_A" name="S1"/>
<subvertex xmi:type="uml:State" xmi:id="_FAvg4P8fEeW45bORGB4c_A" name="S2"/>
<subvertex xmi:type="uml:Pseudostate" xmi:id="_Fg0IEP8fEeW45bORGB4c_A"/>
</region>
</packagedElement>
<packagedElement xmi:type="uml:Signal" xmi:id="_L01D0P8fEeW45bORGB4c_A" name="E1"/>
<packagedElement xmi:type="uml:SignalEvent" xmi:id="_NeH84P8fEeW45bORGB4c_A" name="SignalEventE1" signal="_L01D0P8fEeW45bORGB4c_A"/>
</uml:Model>
自动生成xml,不需要书写其余代码,但是要将生成的UML.xml文件加载;
step2 应用Papyrus创建UML
在工程内创建UML文件目录 resources/model,并new一个Papyrus Model >model目录右键>new>other>
创建完成后打开XX.di文件,运行Create View;
开始绘制:
step3 配置状态config
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineModelConfigurer;
import org.springframework.statemachine.config.model.StateMachineModelFactory;
import org.springframework.statemachine.uml.UmlStateMachineModelFactory;
@Configuration
@EnableStateMachine
public class StateMachineSimpleConfig extends StateMachineConfigurerAdapter<String, String> {
//配置
@Override
public void configure(StateMachineModelConfigurer<String, String> model) throws Exception {
model
.withModel()
.factory(modelFactory());
}
//通过Resource创建model对象,传入UML文件地址
@Bean
public StateMachineModelFactory<String, String> modelFactory() {
Resource model = new ClassPathResource("model/sm-simple.uml");
return new UmlStateMachineModelFactory(model);
}
}
step4 创建监听
import org.springframework.statemachine.annotation.OnTransition;
import org.springframework.statemachine.annotation.OnTransitionEnd;
import org.springframework.statemachine.annotation.OnTransitionStart;
import org.springframework.statemachine.annotation.WithStateMachine;
@WithStateMachine
public class StateMachineSimpleListener {
//监听执行器
@OnTransition(target = "T1")
public void init() {
System.err.println("--------- INIT T1 -----------");
}
//监听执行器
@OnTransition(source = "T1", target = "T2")
public void create() {
System.err.println("---------T1 -> T2-----------");
}
//监听执行器
@OnTransition(source = "T2", target = "T3")
public void S2toS5() {
System.err.println("---------T2 -> T3---------");
}
}
step5 测试
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.test.context.junit4.SpringRunner;
import com.bfxy.statemachine.constant.Events;
import com.bfxy.statemachine.constant.States;
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
@Test
public void contextLoads() {
}
//注入的stateMachineSimple名字必须与UML文件名字一致
@Autowired
private StateMachine<String, String> stateMachineSimple;
@Test
public void testSimple() throws Exception {
stateMachineSimple.start();
stateMachineSimple.sendEvent(MessageBuilder.withPayload("K1").build());
stateMachineSimple.sendEvent(MessageBuilder.withPayload("K2").build());
}
}