apache mina 学习(十二)-----状态机(stateMachine)

2023-12-09 04:58

本文主要是介绍apache mina 学习(十二)-----状态机(stateMachine),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

mina状态机的工作原理:

mina中引入了StateContext对象,顾名思义是一个状态上下文对象,用来保存当前的状态,当代理state对象的方法被调用的时候,这个上下文对象会通知stateContextLookup的实例去从方法参数中获取stateContext,通常情况下StateContextLookup 的实现类会循环方法的参数进行查找,并创建指定的对象,并从这个对象中得到一个上下文对象,如果没定义上下文对象,StateContextLookup 会创建一个新的并存放到对象中。

当代理mina的IoHandler时,我们将用IoSessionStateContextLookup实例来查找Iosession中的参数,然后用IoSession的属性来为每一个Session存储一个StateContext对象。这样同样的状态机可以让每个mina的session使用,而不会彼此影响。

我们使用StateMachineProxyBuilder创建一个代理时,我们一直没有我们一直没有配置StateContextLookup 使用哪种实现。如果没有配置,系统会使用SingletonStateContextLookup 。SingletonStateContextLookup 总是不理会方法中传递给它的参数,它一直返回一个相同的状态上下文。很明显,这中方式在多个客户端
并发的情况下使用同一个同一个状态机是没有意义的。

请努力看懂下面的例子:这个事件Event {id = "messageReceived", arguments =[ArrayList a = [...], Integer b = 1024]}下面的方法将和这个事件是等价的:

// All method arguments matches all event arguments directly
@Transition(on = "messageReceived")
public void messageReceived(ArrayList l, Integer i) { ... }// Matches since ((a instanceof List && b instanceof Number) == true)
@Transition(on = "messageReceived")
public void messageReceived(List l, Number n) { ... }// Matches since ((b instanceof Number) == true)
@Transition(on = "messageReceived")
public void messageReceived(Number n) { ... }// Methods with no arguments always matches
@Transition(on = "messageReceived")
public void messageReceived() { ... }// Methods only interested in the current Event or StateContext always matches
@Transition(on = "messageReceived")
public void messageReceived(StateContext context) { ... }// Matches since ((a instanceof Collection) == true)
@Transition(on = "messageReceived")
public void messageReceived(Event event, Collection c) { ... }

但是下面的方法不会和这个事件相匹配:

// Incorrect ordering
@Transition(on = "messageReceived")
public void messageReceived(Integer i, List l) { ... }// ((a instanceof LinkedList) == false)
@Transition(on = "messageReceived")
public void messageReceived(LinkedList l, Number n) { ... }// Event must be first argument
@Transition(on = "messageReceived")
public void messageReceived(ArrayList l, Event event) { ... }// StateContext must be second argument if Event is used
@Transition(on = "messageReceived")
public void messageReceived(Event event, ArrayList l, StateContext context) { ... }// Event must come before StateContext
@Transition(on = "messageReceived")
public void messageReceived(StateContext context, Event event) { ... }

状态继承:

StateMachine.handle(Event)方法如果不能找到一个transaction和当前的事件在当前的状态中匹配的话就是去找他得父状态,依次类推,知道找到为止,所以我们有时候很需要状态的继承:

@State    public static final String A = "A";
@State(A) public static final String B = "A->B";
@State(A) public static final String C = "A->C";
@State(B) public static final String D = "A->B->D";
@State(C) public static final String E = "A->C->E";
运行:

public static void main(String[] args) {...deck.load("The Knife - Silent Shout");deck.play();deck.pause();deck.play();deck.stop();deck.eject();deck.play();
}
可能会保以下的错误,至少我第一次是报错的:

...
Tape stopped
Tape ejected
Exception in thread "main" o.a.m.sm.event.UnhandledEventException: 
Unhandled event: org.apache.mina.statemachine.event.Event@15eb0a9[id=play,...]at org.apache.mina.statemachine.StateMachine.handle(StateMachine.java:285)at org.apache.mina.statemachine.StateMachine.processEvents(StateMachine.java:142)
这个异常我们无法处理,所以 我们将添加一个指定的事务来处理所有不能匹配的事件:

@Transitions({@Transition(on = "*", in = EMPTY, weight = 100),@Transition(on = "*", in = LOADED, weight = 100),@Transition(on = "*", in = PLAYING, weight = 100),@Transition(on = "*", in = PAUSED, weight = 100)
})
public void error(Event event) {System.out.println("Cannot '" + event.getId() + "' at this time");
}
运行:

Tape stopped
Tape ejected
Cannot 'play' at this time.
当然,定义所有状态的root更有效:

public static class TapeDeckHandler {@State public static final String ROOT = "Root";@State(ROOT) public static final String EMPTY = "Empty";@State(ROOT) public static final String LOADED = "Loaded";@State(ROOT) public static final String PLAYING = "Playing";@State(ROOT) public static final String PAUSED = "Paused";...@Transition(on = "*", in = ROOT)public void error(Event event) {System.out.println("Cannot '" + event.getId() + "' at this time");}
}




这篇关于apache mina 学习(十二)-----状态机(stateMachine)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/472546

相关文章

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

Apache Ignite缓存基本操作实例详解

《ApacheIgnite缓存基本操作实例详解》文章介绍了ApacheIgnite中IgniteCache的基本操作,涵盖缓存获取、动态创建、销毁、原子及条件更新、异步执行,强调线程池注意事项,避免... 目录一、获取缓存实例(Getting an Instance of a Cache)示例代码:二、动态

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

SpringBoot整合Apache Flink的详细指南

《SpringBoot整合ApacheFlink的详细指南》这篇文章主要为大家详细介绍了SpringBoot整合ApacheFlink的详细过程,涵盖环境准备,依赖配置,代码实现及运行步骤,感兴趣的... 目录1. 背景与目标2. 环境准备2.1 开发工具2.2 技术版本3. 创建 Spring Boot

Linux中修改Apache HTTP Server(httpd)默认端口的完整指南

《Linux中修改ApacheHTTPServer(httpd)默认端口的完整指南》ApacheHTTPServer(简称httpd)是Linux系统中最常用的Web服务器之一,本文将详细介绍如何... 目录一、修改 httpd 默认端口的步骤1. 查找 httpd 配置文件路径2. 编辑配置文件3. 保存

Spring Boot 整合 Apache Flink 的详细过程

《SpringBoot整合ApacheFlink的详细过程》ApacheFlink是一个高性能的分布式流处理框架,而SpringBoot提供了快速构建企业级应用的能力,下面给大家介绍Spri... 目录Spring Boot 整合 Apache Flink 教程一、背景与目标二、环境准备三、创建项目 & 添

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

Apache 高级配置实战之从连接保持到日志分析的完整指南

《Apache高级配置实战之从连接保持到日志分析的完整指南》本文带你从连接保持优化开始,一路走到访问控制和日志管理,最后用AWStats来分析网站数据,对Apache配置日志分析相关知识感兴趣的朋友... 目录Apache 高级配置实战:从连接保持到日志分析的完整指南前言 一、Apache 连接保持 - 性

apache的commons-pool2原理与使用实践记录

《apache的commons-pool2原理与使用实践记录》ApacheCommonsPool2是一个高效的对象池化框架,通过复用昂贵资源(如数据库连接、线程、网络连接)优化系统性能,这篇文章主... 目录一、核心原理与组件二、使用步骤详解(以数据库连接池为例)三、高级配置与优化四、典型应用场景五、注意事