Apache Commons SCXML:有限状态机实现

本文提到有限状态机(FSM),SCXML(状态图可扩展标记语言)和Apache Common的SCXML库。 本文还提供了基本的ATM有限状态机示例代码。

有限状态机:

您可能还记得计算机科学课程中的有限状态机。 FSM用于设计计算机程序或数字电路。

有限状态机样本[2]



FSM只是一种抽象机器,可以处于有限状态中的一种。该机器一次仅处于一种状态;

它在任何给定时间所处的状态称为当前状态。

当由触发事件或条件启动时,它可以从一种状态更改为另一种状态,这称为过渡。

特定的FSM由来自每个当前状态的可能过渡状态列表以及每个过渡的触发条件定义。

SCXML语言:

可以使用称为SCXML (用于控制抽象的状态机表示法,由W3C出版)的工作草案来描述复杂的状态机。 SCXML是基于xml的通用状态机语言。 它仍然是草案,最新版本是2012年2月16日。单击此处以获取有关SCXML文档的五分钟介绍。

Apache Commons SCXML库:

Apache的实现旨在创建和维护Java SCXML引擎,该引擎能够执行使用SCXML文档定义的状态机,同时抽象出环境接口。 最新的稳定版本是0.9。

  • 图书馆网站: http : //commons.apache.org/scxml/index.html
  • Eclipse插件: http//commons.apache.org/sandbox/gsoc/2010/scxml-eclipse/ (仍在开发中)
  • 用例: http : //commons.apache.org/scxml/usecases.html

SCXML编辑器:

Apache的Eclipse插件旨在提供一个可视化编辑器来编辑SCXML文件,但它仍在开发中。 还有一个非常成功的scxml gui( http://code.google.com/p/scxmlgui/ )。 您也可以查看State Forge的可视状态机图: http : //www.stateforge.com/StateMachineDiagram/StateMachineDiagram.html

代码示例:

在本文的这一部分中,我们将实现一个基本的ATM状态状态机。 作为简要信息,我们假设ATM可以具有以下状态。 :

  • 空闲:当ATM没有任何活动时,只是将其关闭
  • 加载:当空闲的atm尝试连接到ATM服务器时,配置和信息开始加载
  • 服务中断:如果ATM加载失败或ATM关闭
  • 在服务 :如果ATM老丁是成功或ATM被启动
  • 断开连接:如果ATM未连接到网络

很抱歉缺少有关ATM状态的信息。 这只是一个例子。 首先使用scxmlgui程序绘制状态机。 一个人可以编写自己的scxml文件,但是scxmlgui会为您完成这项艰巨的任务。 这是描述ATM的状态变化的状态图:

以及输出SCXML文件,该文件描述了上图中的转换:

<scxml initial="idle" name="atm.connRestored" version="0.9" xmlns="http://www.w3.org/2005/07/scxml"><state id="idle"><transition event="atm.connected" target="loading"></transition></state><state id="loading"><transition event="atm.loadSuccess" target="inService"></transition><transition event="atm.connClosed" target="disconnected"></transition><transition event="atm.loadFail" target="outOfService"></transition></state><state id="inService"><transition event="atm.shutdown" target="outOfService"></transition><transition event="atm.connLost" target="disconnected"></transition></state><state id="outOfService"><transition event="atm.startup" target="inService"></transition><transition event="atm.connLost" target="disconnected"></transition></state><state id="disconnected"><transition event="atm.connRestored" target="inService"></transition></state></scxml>

我们的FSM实现在AtmStatusFSM类中。

  • AtmStatusFSM类扩展了org.apache.commons.scxml.env.AbstractStateMachine。
  • 通过向超级构造函数提供scxml文件( atm_status.xml )路径来配置FSM。
  • ATM状态更改由事件控制。 当使用相关事件名称[例如fireEvent('atm.connected')]调用fireEvent方法时,FSM状态将自动更新。 您可以随时获取当前状态。
  • 您还可以编写具有FSM状态名称的公共方法。 当相应状态被激活时,将调用这些方法。
package net.javafun.example.atmstatusfsm;import java.util.Collection;
import java.util.Set;import org.apache.commons.scxml.env.AbstractStateMachine;
import org.apache.commons.scxml.model.State;/*** Atm Status Finite State Machine* * @see  Apache Commons Scxml Library * @author ozkansari.com**/
public class AtmStatusFSM extends AbstractStateMachine {/*** State Machine uses this scmxml config file*/private static final String SCXML_CONFIG_ATM_STATUS = "net/javafun/example/atmstatusfsm/atm_status.xml";/** CONSTRUCTOR(S) */public AtmStatusFSM() {super(AtmStatusFSM.class.getClassLoader().getResource(SCXML_CONFIG_ATM_STATUS));}/** HELPER METHOD(S) *//*** Fire the event*/public void firePreDefinedEvent(AtmStatusEventEnum eventEnum){System.out.println("EVENT: " + eventEnum);this.fireEvent(eventEnum.getEventName());}public void callState(String name){this.invoke(name);}/*** Get current state ID as string*/public String getCurrentStateId() {Set states = getEngine().getCurrentStatus().getStates();State state = (State) states.iterator().next();return state.getId();}/*** Get current state as apache's State object*/public State getCurrentState() {Set states = getEngine().getCurrentStatus().getStates();return ( (State) states.iterator().next());}/*** Get events belongs to current status of the FSM*/public Collection getCurrentStateEvents() {return getEngine().getCurrentStatus().getEvents();}/** STATES */// Each method below is the activity corresponding to a state in the// SCXML document (see class constructor for pointer to the document).public void idle() {System.out.println("STATE: idle");}public void loading() {System.out.println("STATE: loading");}public void inService() {System.out.println("STATE: inService");}public void outOfService() {System.out.println("STATE: outOfService");}public void disconnected() {System.out.println("STATE: disconnected");}
}

我们有以下枚举文件来描述我们的事件。 您不必编写此类代码,但这可能有助于定义事件。 您还可以使用getEngine()。getCurrentStatus()。getEvents()代码片段动态获取这些事件。

package net.javafun.example.atmstatusfsm;/*** Atm Status Change Events* * @author ozkansari.com**/
public enum AtmStatusEventEnum {CONNECT("atm.connected"), CONNECTION_CLOSED("atm.connClosed"),CONNECTION_LOST("atm.connLost"),CONNECTION_RESTORED("atm.connRestored"),LOAD_SUCCESS("atm.loadSuccess"),LOAD_FAIL("atm.loadFail"),SHUTDOWN("atm.shutdown"),STARTUP("atm.startup");private final String eventName;private AtmStatusEventEnum(String eventName) {this.eventName = eventName;}public String getEventName() {return eventName;}public static String getNamesAsCsv(){StringBuilder sb = new StringBuilder();for (AtmStatusEventEnum e : AtmStatusEventEnum.values()) {sb.append(e.name());sb.append(",");}return sb.substring(0,sb.length()-2);}}

您可以在下面看到基本的GUI代码。 GUI首先显示可能触发的事件。 选择并提交事件后,将显示当前的ATM状态,并更新事件列表。

package net.javafun.example.atmstatusfsm;import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;import org.apache.commons.scxml.model.Transition;/*** Atm Status Change GUI* * @author ozkansari.com**/
public class AtmDisplay extends JFrame implements ActionListener {private static final long serialVersionUID = -5083315372455956151L;private AtmStatusFSM atmStatusFSM;private JButton button;private JLabel state;private JComboBox eventComboBox = new JComboBox();public static void main(String[] args) {new AtmDisplay();}public AtmDisplay() {super("ATM Display Demo");atmStatusFSM = new AtmStatusFSM();setupUI();}@SuppressWarnings("deprecation")private void setupUI() {JPanel panel = new JPanel();panel.setLayout(new BorderLayout());setContentPane(panel);button = makeButton("FIRE_EVENT", AtmStatusEventEnum.getNamesAsCsv(), "Submit" );panel.add(button, BorderLayout.CENTER);state = new JLabel(atmStatusFSM.getCurrentStateId());panel.add(state, BorderLayout.SOUTH);initEvents();panel.add(eventComboBox, BorderLayout.NORTH);pack();setLocation(200, 200);setResizable(false);setSize(300, 125);show();setDefaultCloseOperation(EXIT_ON_CLOSE);}@SuppressWarnings("unchecked")private void initEvents() {eventComboBox.removeAllItems();List transitionList = atmStatusFSM.getCurrentState().getTransitionsList();for (Transition transition : transitionList) {eventComboBox.addItem(transition.getEvent() );}}public void actionPerformed(ActionEvent e) {String command = e.getActionCommand();if(command.equals("FIRE_EVENT")) {checkAndFireEvent();}}private boolean checkAndFireEvent() {atmStatusFSM.fireEvent(eventComboBox.getSelectedItem().toString());state.setText(atmStatusFSM.getCurrentStateId());initEvents();repaint();return true;}private JButton makeButton(final String actionCommand, final String toolTipText, final String altText) {JButton button = new JButton(altText);button.setActionCommand(actionCommand);button.setToolTipText(toolTipText);button.addActionListener(this);button.setOpaque(false);return button;}}

我们的简单程序的输出:

下图给出了Eclipse中显示的项目文件(带有必需的库): 有关完整的源代码,请访问https://github.com/ozkansari/atmstatemachine

参考:来自Java Fun博客的JCG合作伙伴 Ozkan SARI的Apache Commons SCXML轻松有限状态机实现 。

翻译自: https://www.javacodegeeks.com/2012/06/apache-commons-scxml-finite-state.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372400.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第二十章、分离应用程序逻辑并处理事件

理解委托 委托是对方法的引用。&#xff08;之所以称为委托&#xff0c;是因为一旦被调用&#xff0c;就将具体的处理“委托”给引用的方法&#xff09; 委托对象引用了方法&#xff0c;和将int赋值给int变量一样&#xff0c;是将方法引用赋给委托对象。 Processor p new Proc…

pymol怎么做底物口袋表面_怎么从文献中发掘一篇新文章?

本文来自微信公众号&#xff1a;X-MOLNews可能你的导师也曾说过这样的话——盯着Nature、Science级别的文章做&#xff0c;可能最终会中十分的文章&#xff1b;如果盯着十分的文章做&#xff0c;可能最终发出来也就五六分&#xff1b;但如果就为了发个文章混毕业&#xff0c;很…

如何分析线程转储– IBM VM

本文是我们的线程转储分析系列的第4部分&#xff0c;它将为您概述什么是IBM VM的JVM线程转储以及您将找到的不同线程和数据点。 您将看到和学习​​到&#xff0c;IBM VM Thread Dump格式是不同的&#xff0c;但是提供了更多现成的故障排除数据。 在这一点上&#xff0c;您应该…

VMware vSphere克隆虚拟机

参考资料&#xff1a;http://blog.csdn.net/shen_jz2012/article/details/484167711. 首先将你所要克隆的虚拟机关掉2. 选择你的ESXI服务器选中"配置"&#xff0c;然后选中存储器右键你的存储介质&#xff0c;比如我的是datastore1&#xff0c;选择“浏览数据存储”。…

将本地jar包倒入maven项目类库中

有两种方法&#xff1a;1.本地下载maven并配置环境变量&#xff0c;然后运行cmd控制台输入 mvn install:install-file -Dfile本地jar路径 -DgroupId -DartifactId -Dpackagingjar -Dversion -DgeneratePomtrue. 2.直接在pom.xml中对应的依赖下面添加<scope>system&l…

Spring和JSF集成:分页

处理大型数据集时&#xff0c;通常需要以分页格式显示数据。 分页是一个有趣的问题&#xff0c;因为它倾向于跨越应用程序的所有层&#xff0c;从视图层通过应用程序服务一直到对数据库的原始调用。 在获取分页数据时&#xff0c;有一些非常好的解决方案。 如果您使用的是JPA&a…

三重积分平均值_直角坐标系下的三重积分的几何可视化解释图解高等数学

12.4 直角坐标系下的三重积分三重积分假设 F(x,y,z) 为一个空间有界闭区域 D 上的函数. D 为下面立体椭球所占区域. 将空间区域分割成小长方块. 体积记为 ΔVk, 其长宽高分别为Δxk, Δyk, Δzk , 并有下列的求和式:观察下面动画, 当空间不断分割, 每个小方块的体积 ΔVk 不断变…

最短网络Agri-Net

【例4-11】、最短网络Agri-Net【问题描述】农民约翰被选为他们镇的镇长&#xff01;他其中一个竞选承诺就是在镇上建立起互联网&#xff0c;并连接到所有的农场。当然&#xff0c;他需要你的帮助。约翰已经给他的农场安排了一条高速的网络线路&#xff0c;他想把这条线路共享给…

cors-synchronous-requests-not-working-in-firefox

http://stackoverflow.com/questions/16668386/cors-synchronous-requests-not-working-in-firefox转载于:https://www.cnblogs.com/diyunpeng/p/5829594.html

硬盘接口协议

硬盘是电脑主要的存储媒介之一&#xff0c;由一个或者多个铝制或者玻璃制的碟片组成。碟片外覆盖有铁磁性材料。硬盘有固态硬盘&#xff08;SSD 盘&#xff0c;新式硬盘&#xff09;、机械硬盘&#xff08;HDD 传统硬盘&#xff09;、混合硬盘&#xff08;HHD 一块基于传统机械…

图的表示

Python 数据结构与算法——图&#xff08;Graph&#xff09; 1. 邻接矩阵 vs 邻接表&#xff08;压缩的邻接矩阵&#xff09; 邻接矩阵的缺点是&#xff1a; 空间占用与结点数的平方成正比&#xff0c;可能带来很大的浪费&#xff1b;邻接矩阵不容易增加新的结点&#xff0c;不…

在Java Web应用程序中阻止CSRF

跨站点请求伪造攻击&#xff08;CSRF&#xff09;在Web应用程序中非常常见&#xff0c;如果允许&#xff0c;可能会造成重大危害。 如果您从未听说过CSRF&#xff0c;建议您查看有关它的OWASP页面 。 幸运的是&#xff0c;阻止CSRF攻击非常简单&#xff0c;我将向您展示它们的工…

windows命令行无法启动redis_windows系统安装redis

1、下载最新redis https://github.com/MicrosoftArchive/redis/releases我选择下载msi版本的2.双击下载包安装3.设置redis环境变量&#xff0c;把redis路径配置到系统变量path值中4启动redis&#xff0c;cmd进入安装好redis文件夹 输入&#xff1a;如果redis启动出错Creating S…

SQL Server 筛选时间区间

一、SQL直接判断 select * from login where pass>2013/03/25 and pass < 2017/04/24 二、DATEDIFF() 函数返回两个日期之间的时间 --语法 DATEDIFF(datepart,startdate,enddate) --开始时间 startdate --结束时间 enddate --datepart datepart缩写年yy, yyyy季度qq, …

OpenShift Express Web管理控制台:入门

本周&#xff0c; 最新版本的OpenShift为已经很棒的PaaS Cloud提供商带来了两个非常好的功能。 首先&#xff0c;JBoss AS已从7.0升级到7.1&#xff0c;并且所有新的Express Web Management Console已作为预览发布。 在本文中&#xff0c;我们将研究如何使用此新控制台&#xf…

Linux-IP地址后边加个/8(16,24,32)是什么意思?

是掩码的位数 A类IP地址的默认子网掩码为255.0.0.0&#xff08;由于255相当于二进制的8位1&#xff0c;所以也缩写成“/8”&#xff0c;表示网络号占了8位&#xff09;; B类的为255.255.0.0&#xff08;/16&#xff09;; C类的为255.255.255.0(/24) /30就是255…

女士细线毛衣起多少针_从起针到缝合,教你织毛衣的各种要点(详细教程)

新手学织毛衣看过来&#xff0c;7大编织要点帮你解决织好一件毛衣的基础问题&#xff0c;满满的干货&#xff0c;每点都值得学习!一、起针二、棒针符号三、如何织小样四、依据小样推算针数收挂肩的推算五、斜肩针数的推算开前、后领的位置与针数六、袖山的推算七、如何上袖子一…

关于OPENSSL的使用

#import <Foundation/Foundation.h> interface RSAEncryptor : NSObject /** * 加密方法 * * param str 需要加密的字符串 * param path .der格式的公钥文件路径 */ (NSString *)encryptString:(NSString *)str publicKeyWithContentsOfFile:(NSString *)path; /*…

Jelastic Java云端平台

谁在Jelastic背后&#xff1f; 那是我的第一个问题&#xff0c;因此我浏览了Jelastic网站。 回答此问题的最佳方法是查看“ Jelastic团队”部分。 创始人&#xff0c;顾问&#xff0c;特殊合作伙伴构成了一支真正的专业团队。 作为特殊的合作伙伴&#xff0c;您会发现MySQL&am…

请先设置tkk_搅拌站水泥罐仓顶除尘器设置及调整

搅拌站水泥罐仓顶除尘器采用脉冲喷吹清灰系统&#xff0c;除尘器本体结构&#xff0c;采用标准模板焊接&#xff0c;整体结构&#xff0c;强度牢靠&#xff0c;组装维修方便&#xff0c;脉冲清灰采用时序控制器MCY系列 控制阀门KEK系列&#xff0c;喷吹清灰频率及喷吹间隔可手…