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"); } }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值