昆山做网站的kamese,网站建设杭州缘择低价,高端网站设计公司如何设计网站,德阳公司网站建设状态机是基于有限状态的计算模型 #xff0c;正如Wikipedia非常明确地说的那样。 通常#xff0c;工作流会与状态一起使用#xff0c;这意味着您不能仅从任何状态进入任何其他状态#xff1a;应遵循一些规则。 这些状态之间的转换受规则限制。 Spring框架具有一个称为Spri… 状态机是基于有限状态的计算模型 正如Wikipedia非常明确地说的那样。 通常工作流会与状态一起使用这意味着您不能仅从任何状态进入任何其他状态应遵循一些规则。 这些状态之间的转换受规则限制。 Spring框架具有一个称为Spring State Machine的完整库 。 它是该概念的实现旨在为已经使用Spring框架的开发人员简化状态机逻辑的开发。 让我们看看它是如何工作的。 首先我们需要一个Spring Boot应用程序该应用程序依赖于Spring State Machine为简化起见还有Lombok。 从Spring Starter页面或从Intellij IDEA之类的IDE也使用Spring starter模板生成一个非常容易。 要实际使用状态机应在应用程序类中启用它 SpringBootApplication
EnableStateMachine
public class Application implements CommandLineRunner {private final StateMachineBookStates, BookEvents stateMachine;Autowiredpublic Application(StateMachineBookStates, BookEvents stateMachine) {this.stateMachine stateMachine;}public static void main(String[] args) {SpringApplication.run(Application.class, args);}Overridepublic void run(String... args) {stateMachine.start();stateMachine.sendEvent(BookEvents.RETURN);stateMachine.sendEvent(BookEvents.BORROW);stateMachine.stop();}
} 使用EnableStateMachine批注时它将在应用程序启动时自动创建默认状态机。 因此可以将其注入Application类。 默认情况下该bean将被称为stateMachine 但是可以给它另一个名称。 我们还需要为我们的活动和州提供课程。 让我们的简单示例基于库。 我们知道图书馆的书籍可以借用或归还也可以损坏和修理因此无法借用。 因此这正是我们放入模型中的内容。 public enum BookStates {AVAILABLE,BORROWED,IN_REPAIR
}
public enum BookEvents {BORROW,RETURN,START_REPAIR,END_REPAIR
} 然后应使用以下事务和状态来配置状态机 Overridepublic void configure(StateMachineStateConfigurerBookStates, BookEvents states) throws Exception {states.withStates().initial(BookStates.AVAILABLE).states(EnumSet.allOf(BookStates.class));}Overridepublic void configure(StateMachineTransitionConfigurerBookStates, BookEvents transitions) throws Exception {transitions.withExternal().source(BookStates.AVAILABLE).target(BookStates.BORROWED).event(BookEvents.BORROW).and().withExternal().source(BookStates.BORROWED).target(BookStates.AVAILABLE).event(BookEvents.RETURN).and().withExternal().source(BookStates.AVAILABLE).target(BookStates.IN_REPAIR).event(BookEvents.START_REPAIR).and().withExternal().source(BookStates.IN_REPAIR).target(BookStates.AVAILABLE).event(BookEvents.END_REPAIR);
} 最后但并非最不重要的一点是我们允许状态机自动启动默认情况下不会启动。 Overridepublic void configure(StateMachineConfigurationConfigurerBookStates, BookEvents config) throws Exception {config.withConfiguration().autoStartup(true);
} 现在我们可以在应用程序中使用它看看会发生什么 Overridepublic void run(String... args) {boolean returnAccepted stateMachine.sendEvent(BookEvents.RETURN);logger.info(return accepted: returnAccepted);boolean borrowAccepted stateMachine.sendEvent(BookEvents.BORROW);logger.info(borrow accepted: borrowAccepted);
} 运行应用程序时我们在日志中看到以下内容 2018-07-07 13:46:05.096 INFO 37417 --- [ main] STATE MACHINE : return accepted: false
2018-07-07 13:46:05.098 INFO 37417 --- [ main] STATE MACHINE : borrow accepted: true 我故意先打电话给RETURN看看它会失败。 但是它无一例外都失败该操作未被接受并且计算机保持在AVAILABLE状态这使得再次执行BORROW成为可能。 那么如果我们交换两个呼叫会怎样 2018-07-07 13:49:46.218 INFO 37496 --- [ main] STATE MACHINE : borrow accepted: true
2018-07-07 13:49:46.218 INFO 37496 --- [ main] STATE MACHINE : return accepted: true 这意味着可以接受正确的交互。 但是如果我们想更清楚地了解发生了什么该怎么办 一种方法是为状态更改配置处理程序 Overridepublic void configure(StateMachineStateConfigurerBookStates, BookEvents states) throws Exception {states.withStates().initial(BookStates.AVAILABLE).state(BookStates.AVAILABLE, entryAction(), exitAction()).state(BookStates.BORROWED, entryAction(), exitAction()).state(BookStates.IN_REPAIR, entryAction(), exitAction());}Beanpublic ActionBookStates, BookEvents entryAction() {return ctx - LOGGER.info(Entry action {} to get from {} to {},ctx.getEvent(),getStateInfo(ctx.getSource()),getStateInfo(ctx.getTarget()));}Beanpublic ActionBookStates, BookEvents exitAction() {return ctx - LOGGER.info(Exit action {} to get from {} to {},ctx.getEvent(),getStateInfo(ctx.getSource()),getStateInfo(ctx.getTarget()));
}2018-07-07 13:53:59.940 INFO 37579 --- [ main] STATE MACHINE : Entry action null to get from EMPTY STATE to AVAILABLE
2018-07-07 13:54:00.051 INFO 37579 --- [ main] STATE MACHINE : return accepted: false
2018-07-07 13:54:00.052 INFO 37579 --- [ main] STATE MACHINE : Exit action BORROW to get from AVAILABLE to BORROWED
2018-07-07 13:54:00.052 INFO 37579 --- [ main] STATE MACHINE : Entry action BORROW to get from AVAILABLE to BORROWED
2018-07-07 13:54:00.053 INFO 37579 --- [ main] STATE MACHINE : borrow accepted: true
2018-07-07 13:54:00.053 INFO 37579 --- [ main] STATE MACHINE : Exit action RETURN to get from BORROWED to AVAILABLE
2018-07-07 13:54:00.053 INFO 37579 --- [ main] STATE MACHINE : Entry action RETURN to get from BORROWED to AVAILABLE
2018-07-07 13:54:00.053 INFO 37579 --- [ main] STATE MACHINE : return accepted: true 另一种方法是定义一个成熟的侦听器 public class LoggingMashineListener implements StateMachineListenerBookStates, BookEvents {private static final Logger LOGGER LoggingUtils.LOGGER;Overridepublic void stateChanged(StateBookStates, BookEvents from, StateBookStates, BookEvents to) {LOGGER.info(State changed from {} to {}, getStateInfo(from), getStateInfo(to));}Overridepublic void stateEntered(StateBookStates, BookEvents state) {LOGGER.info(Entered state {}, getStateInfo(state));}Overridepublic void stateExited(StateBookStates, BookEvents state) {LOGGER.info(Exited state {}, getStateInfo(state));}Overridepublic void eventNotAccepted(Message event) {LOGGER.error(Event not accepted: {}, event.getPayload());}Overridepublic void transition(TransitionBookStates, BookEvents transition) {// Too much logging spoils the code )}Overridepublic void transitionStarted(TransitionBookStates, BookEvents transition) {// Too much logging spoils the code )}Overridepublic void transitionEnded(TransitionBookStates, BookEvents transition) {// Too much logging spoils the code )}Overridepublic void stateMachineStarted(StateMachineBookStates, BookEvents stateMachine) {LOGGER.info(Machine started: {}, stateMachine);}Overridepublic void stateMachineStopped(StateMachineBookStates, BookEvents stateMachine) {LOGGER.info(Machine stopped: {}, stateMachine);}Overridepublic void stateMachineError(StateMachineBookStates, BookEvents stateMachine, Exception exception) {LOGGER.error(Machine error: {}, stateMachine);}Overridepublic void extendedStateChanged(Object key, Object value) {LOGGER.info(Extended state changed: [{}: {}], key, value);}Overridepublic void stateContext(StateContextBookStates, BookEvents stateContext) {// Too much logging spoils the code )}
} 并在配置监听器后将其链接到计算机。 现在我们可以删除进入和退出侦听器并且状态配置将返回到我们的第一个修订版请参见上文。 Overridepublic void configure(StateMachineConfigurationConfigurerBookStates, BookEvents config) throws Exception {config.withConfiguration().autoStartup(true).listener(new LoggingMashineListener());
} 这样您将对正在发生的事情有更多的了解 2018-07-07 13:59:22.714 INFO 37684 --- [ main] STATE MACHINE : Entered state AVAILABLE
2018-07-07 13:59:22.716 INFO 37684 --- [ main] STATE MACHINE : State changed from EMPTY STATE to AVAILABLE
2018-07-07 13:59:22.717 INFO 37684 --- [ main] STATE MACHINE : Machine started: IN_REPAIR AVAILABLE BORROWED / AVAILABLE / uuid815f744e-8c5c-4ab1-88d1-b5223199bc4e / idnull
2018-07-07 13:59:22.835 ERROR 37684 --- [ main] STATE MACHINE : Event not accepted: RETURN
2018-07-07 13:59:22.836 INFO 37684 --- [ main] STATE MACHINE : return accepted: false
2018-07-07 13:59:22.837 INFO 37684 --- [ main] STATE MACHINE : Exited state AVAILABLE
2018-07-07 13:59:22.838 INFO 37684 --- [ main] STATE MACHINE : Entered state BORROWED
2018-07-07 13:59:22.838 INFO 37684 --- [ main] STATE MACHINE : State changed from AVAILABLE to BORROWED
2018-07-07 13:59:22.839 INFO 37684 --- [ main] STATE MACHINE : borrow accepted: true
2018-07-07 13:59:22.839 INFO 37684 --- [ main] STATE MACHINE : Exited state BORROWED
2018-07-07 13:59:22.839 INFO 37684 --- [ main] STATE MACHINE : Entered state AVAILABLE
2018-07-07 13:59:22.839 INFO 37684 --- [ main] STATE MACHINE : State changed from BORROWED to AVAILABLE
2018-07-07 13:59:22.839 INFO 37684 --- [ main] STATE MACHINE : return accepted: true 什么时候需要状态机 Spring文档指出如果满足以下条件您已经在尝试实现状态机 使用布尔标志或枚举对情况进行建模。 具有仅对应用程序生命周期的一部分有意义的变量。 遍历if / else结构并检查是否设置了特定的标志或枚举然后进一步对当标志和枚举的某些组合存在或不存在时的处理方式作进一步的例外。 我可以想到一些示例 机器人 对于状态机来说这通常是一个很好的例子因为机器人通常只有几个状态并且它们之间有不同的动作。 例如您有一个机器人在问问题以预订酒店一个著名的例子。 您会问几个问题位置客人人数价格范围等。每个问题都是一个州。 每个答案都是一个事件可以转换为下一个状态。 物联网 最简单的状态机具有两种状态ON和OFF。 但是使用比电灯开关更复杂的设备可能会在它们之间存在更多状态并且会有更多事件进行状态转换。 Spring State Machine可以做的事情还很多。 例如 状态可以嵌套 。 此外还有可以配置为检查是否允许过渡的防护措施 以及允许定义选择状态接合状态等的 伪状态。 事件可以由操作或在计时器上触发 。 状态机可以持久化以提高性能。 要浏览所有内容您需要研究Spring State Machine文档并确定适合您的特定情况的文档。 在这里我们仅轻轻地刮擦了表面。 您可以观看有关Spring State Machine的视频 或研究完整的规范以了解有关该主题的更多信息。 可以在这里找到本文的项目源。 翻译自: https://www.javacodegeeks.com/2018/07/spring-state-machine.html