设为首页 收藏本站
查看: 545|回复: 0

[经验分享] apache mina 学习(十二)-----状态机(stateMachine)

[复制链接]

尚未签到

发表于 2017-1-7 07:45:49 | 显示全部楼层 |阅读模式
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 stoppedTape ejectedException 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 stoppedTape ejectedCannot '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");}}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-324848-1-1.html 上篇帖子: 用Apache实现虚拟主机服务 下篇帖子: apache mina 学习(一)-----时间服务器
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表