持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
状态机
状态机是一种用来进行对象行为建模的工具,其作用主要是描述对象在它的生命周期内所经历的状态序列,以及如何响应来自外界的各种事件。摘录自这个大神的文章状态机引擎选型
需注意的是状态机并不是流程引擎,没有流程图及其它元素,仅包含状态,事件等相关内容。
示例说明
网上能找到的示例大多都过于复杂,所以写了一个简单的示例下面的代码定义了一个极简的状态机,仅包含两个状态(上班,下班),一个事件(通勤),通过web页面操作添加状态机及状态转换,集成了spring-statemachine-data-jpa进行持久化.
SpringBoot2.x配置说明
- Pom.xml
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-starter</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-data-jpa</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
JAVA配置
持久化配置
@Configuration
public class StateMachineJpaConfig {
/**
* StateMachineRuntimePersister为状态机运行时持久化配置
* @param jpaStateMachineRepository
* @return
*/
@Bean
public StateMachineRuntimePersister<String, String, String> stateMachineRuntimePersister(
JpaStateMachineRepository jpaStateMachineRepository) {
return new JpaPersistingStateMachineInterceptor<>(jpaStateMachineRepository);
}
/**
* StateMachineService为状态状态机持久化控制,用于获取或关闭状态机
* @param stateMachineFactory
* @param stateMachineRuntimePersister
* @return
*/
@Bean
public StateMachineService<String, String> stateMachineService(
StateMachineFactory<String, String> stateMachineFactory,
StateMachineRuntimePersister<String, String, String> stateMachineRuntimePersister) {
return new DefaultStateMachineService<String, String>(stateMachineFactory, stateMachineRuntimePersister);
}
}
-
JpaStateMachineRepository:具体数据层操作
-
StateMachineService: 服务层操作,业务使用时注入即可
状态机配置
@EnableStateMachine为单例模式通常用于维护一个状态,并不适合此示例所以使用@EnableStateMachineFactory
@Configuration
@EnableStateMachineFactory
public class StateMachineConfig extends StateMachineConfigurerAdapter<String, String> {
@Autowired
private StateMachineRuntimePersister<String, String, String> stateMachineRuntimePersister;
@Autowired
private StateMachineLogListener logListener;
@Override
public void configure(StateMachineConfigurationConfigurer<String, String> config)
throws Exception {
config
.withPersistence()
.runtimePersister(stateMachineRuntimePersister)
.and()
.withConfiguration().listener(logListener);
}
@Override
public void configure(StateMachineStateConfigurer<String, String> states)
throws Exception {
states
.withStates()
.initial("宿舍")
.state("公司");
}
@Override
public void configure(StateMachineTransitionConfigurer<String, String> transitions)
throws Exception {
transitions
.withExternal()
.source("宿舍").target("公司")
.event("通勤")
.and()
.withExternal()
.source("公司").target("宿舍")
.event("通勤");
}
}
- StateMachineStateConfigurer:状态配置,可有多个状态,初始为initial,结束为end,示例为了方便只配置了初始状态,其它配置请查阅文档。
- StateMachineTransitionConfigurer:事件与状态关联配置。
监听配置
继承StateMachineListenerAdapter重写需监听的方法即可,通过方法名可推测监听的事件,就不详细介绍了。
@Slf4j
@Component
public class StateMachineLogListener extends StateMachineListenerAdapter<String, String> {
private StateContext stateContext;
@Override
public void stateChanged(State<String, String> from, State<String, String> to) {
if(stateContext!=null){
log.info("{} in stateChanged Listener",stateContext.getStateMachine().getId());
}else{
log.info("---------------------stateChanged---------------------------------------");
}
}
@Override
public void stateEntered(State<String, String> state) {
if(stateContext!=null){
log.info("{} in stateEntered Listener",stateContext.getStateMachine().getId());
}else{
log.info("---------------------stateEntered---------------------------------------");
}
}
@Override
public void stateExited(State<String, String> state) {
if(stateContext!=null){
log.info("{} in stateExited Listener",stateContext.getStateMachine().getId());
}else{
log.info("---------------------stateExited---------------------------------------");
}
}
@Override
public void eventNotAccepted(Message<String> event) {
if(stateContext!=null){
log.info("{} in eventNotAccepted Listener",stateContext.getStateMachine().getId());
}else{
log.info("---------------------eventNotAccepted---------------------------------------");
}
}
@Override
public void transition(Transition<String, String> transition) {
if(stateContext!=null){
log.info("{} in transition Listener",stateContext.getStateMachine().getId());
}else{
log.info("---------------------transition---------------------------------------");
}
}
@Override
public void transitionStarted(Transition<String, String> transition) {
if(stateContext!=null){
log.info("{} in transitionStarted Listener",stateContext.getStateMachine().getId());
}else{
log.info("---------------------transitionStarted---------------------------------------");
}
}
@Override
public void transitionEnded(Transition<String, String> transition) {
if(stateContext!=null){
log.info("{} in transitionEnded Listener",stateContext.getStateMachine().getId());
}else{
log.info("---------------------transitionEnded---------------------------------------");
}
}
@Override
public void stateMachineStarted(StateMachine<String, String> stateMachine) {
if(stateContext!=null){
log.info("{} in stateMachineStarted Listener",stateContext.getStateMachine().getId());
}else{
log.info("---------------------stateMachineStarted---------------------------------------");
}
}
@Override
public void stateMachineStopped(StateMachine<String, String> stateMachine) {
if(stateContext!=null){
log.info("{} in stateMachineStopped Listener",stateContext.getStateMachine().getId());
}else{
log.info("---------------------stateMachineStopped---------------------------------------");
}
}
@Override
public void stateMachineError(StateMachine<String, String> stateMachine, Exception exception) {
if(stateContext!=null){
log.info("{} in stateMachineError Listener",stateContext.getStateMachine().getId());
}else{
log.info("---------------------stateMachineError---------------------------------------");
}
}
@Override
public void extendedStateChanged(Object key, Object value) {
if(stateContext!=null){
log.info("{} in extendedStateChanged Listener",stateContext.getStateMachine().getId());
}else{
log.info("---------------------extendedStateChanged---------------------------------------");
}
}
@Override
public void stateContext(StateContext<String, String> stateContext) {
if(stateContext!=null){
this.stateContext = stateContext;
log.info("{} in stateContext Listener",stateContext.getStateMachine().getId());
}else{
log.info("---------------------stateContext---------------------------------------");
}
}
}