Mina状态机StateMachine()

接下来我们要把这样的方式用在通信中。用通信的方式来模拟录放机的按钮。

我们先看状态的定义:

001 package com.a2.desktop.example10.mina.statemachine;
002  
003 import static org.apache.mina.statemachine.event.IoHandlerEvents.EXCEPTION_CAUGHT;
004 import static org.apache.mina.statemachine.event.IoHandlerEvents.MESSAGE_RECEIVED;
005 import static org.apache.mina.statemachine.event.IoHandlerEvents.SESSION_OPENED;
006  
007 import org.apache.mina.core.future.IoFutureListener;
008 import org.apache.mina.core.session.IoSession;
009  
010 import org.apache.mina.statemachine.StateControl;
011 import org.apache.mina.statemachine.annotation.IoHandlerTransition;
012 import org.apache.mina.statemachine.annotation.IoHandlerTransitions;
013 import org.apache.mina.statemachine.annotation.State;
014 import org.apache.mina.statemachine.context.AbstractStateContext;
015 import org.apache.mina.statemachine.context.StateContext;
016 import org.apache.mina.statemachine.event.Event;
017  
018 public class TapeDeckServer {
019  
020     @State
021     public static final String ROOT = "Root";
022     @State(ROOT)
023     // 表示继承关系
024     public static final String EMPTY = "Empty";
025     @State(ROOT)
026     public static final String LOADED = "Loaded";
027     @State(ROOT)
028     public static final String PLAYING = "Playing";
029     @State(ROOT)
030     public static final String PAUSED = "Paused";
031  
032     private final String[] tapes = { "盖世英雄-王力宏""唯一-王力宏" };
033  
034     static class TapeDeckContext extends AbstractStateContext {
035         public String tapeName;
036     }
037      
038      @IoHandlerTransition(on = SESSION_OPENED, in = EMPTY)
039         public void connect(IoSession session) {
040             session.write("+ Greetings from your tape deck!");
041         }
042          
043         @IoHandlerTransition(on = MESSAGE_RECEIVED, in = EMPTY, next = LOADED)
044         public void loadTape(TapeDeckContext context, IoSession session, LoadCommand cmd) {
045       
046             if (cmd.getTapeNumber() < 1 || cmd.getTapeNumber() > tapes.length) {
047                 session.write("- Unknown tape number: " + cmd.getTapeNumber());
048                 StateControl.breakAndGotoNext(EMPTY);
049             else {
050                 context.tapeName = tapes[cmd.getTapeNumber() - 1];
051                 session.write("+ \"" + context.tapeName + "\" loaded");
052             }
053         }
054  
055         @IoHandlerTransitions({
056             @IoHandlerTransition(on = MESSAGE_RECEIVED, in = LOADED, next = PLAYING),
057             @IoHandlerTransition(on = MESSAGE_RECEIVED, in = PAUSED, next = PLAYING)
058         })
059         public void playTape(TapeDeckContext context, IoSession session, PlayCommand cmd) {
060             session.write("+ Playing \"" + context.tapeName + "\"");
061         }
062          
063         @IoHandlerTransition(on = MESSAGE_RECEIVED, in = PLAYING, next = PAUSED)
064         public void pauseTape(TapeDeckContext context, IoSession session, PauseCommand cmd) {
065             session.write("+ \"" + context.tapeName + "\" paused");
066         }
067          
068         @IoHandlerTransition(on = MESSAGE_RECEIVED, in = PLAYING, next = LOADED)
069         public void stopTape(TapeDeckContext context, IoSession session, StopCommand cmd) {
070             session.write("+ \"" + context.tapeName + "\" stopped");
071         }
072          
073         @IoHandlerTransition(on = MESSAGE_RECEIVED, in = LOADED, next = EMPTY)
074         public void ejectTape(TapeDeckContext context, IoSession session, EjectCommand cmd) {
075             session.write("+ \"" + context.tapeName + "\" ejected");
076             context.tapeName = null;
077         }
078          
079         @IoHandlerTransition(on = MESSAGE_RECEIVED, in = ROOT)
080         public void listTapes(IoSession session, ListCommand cmd) {
081             StringBuilder response = new StringBuilder("+ (");
082             for (int i = 0; i < tapes.length; i++) {
083                 response.append(i + 1).append(": ");
084                 response.append('"').append(tapes[i]).append('"');
085                 if (i < tapes.length - 1) {
086                     response.append(", ");
087                 }
088             }
089             response.append(')');
090             session.write(response);
091         }
092          
093         @IoHandlerTransition(on = MESSAGE_RECEIVED, in = ROOT)
094         public void info(TapeDeckContext context, IoSession session, InfoCommand cmd) {
095             String state = context.getCurrentState().getId().toLowerCase();
096             if (context.tapeName == null) {
097                 session.write("+ Tape deck is " + state + "");
098             else {
099                 session.write("+ Tape deck is " + state
100                         ". Current tape: \"" + context.tapeName + "\"");
101             }
102         }
103          
104         @IoHandlerTransition(on = MESSAGE_RECEIVED, in = ROOT)
105         public void quit(TapeDeckContext context, IoSession session, QuitCommand cmd) {
106             session.write("+ Bye! Please come back!").addListener(IoFutureListener.CLOSE);
107         }
108          
109         @IoHandlerTransition(on = MESSAGE_RECEIVED, in = ROOT, weight = 10)
110         public void error(Event event, StateContext context, IoSession session, Command cmd) {
111             session.write("- Cannot " + cmd.getName()
112                     " while " + context.getCurrentState().getId().toLowerCase());
113         }
114          
115         @IoHandlerTransition(on = EXCEPTION_CAUGHT, in = ROOT)
116         public void commandSyntaxError(IoSession session, CommandSyntaxException e) {
117             session.write("- " + e.getMessage());
118         }
119          
120         @IoHandlerTransition(on = EXCEPTION_CAUGHT, in = ROOT, weight = 10)
121         public void exceptionCaught(IoSession session, Exception e) {
122             e.printStackTrace();
123             session.close(true);
124         }
125          
126         @IoHandlerTransition(in = ROOT, weight = 100)
127         public void unhandledEvent() {
128         }
129          
130 }

命令的抽象类:

1 package com.a2.desktop.example10.mina.statemachine;
2  
3 public abstract class Command {
4      public abstract String getName();
5 }

以下是各类命令,实现形式相似:

01 package com.a2.desktop.example10.mina.statemachine;
02  
03 public class LoadCommand extends Command {
04      
05     public static final String NAME = "load";
06  
07     private final int tapeNumber;
08  
09     public LoadCommand(int tapeNumber) {
10         this.tapeNumber = tapeNumber;
11     }
12  
13     public int getTapeNumber() {
14         return tapeNumber;
15     }
16  
17     @Override
18     public String getName() {
19         return NAME;
20     }
21  
22 }
23  
24 package com.a2.desktop.example10.mina.statemachine;
25  
26 public class PlayCommand extends Command {
27  
28     public static final String NAME = "play";
29  
30     @Override
31     public String getName() {
32         return NAME;
33     }
34 }
35 //以下省略各种命令…

下面是解码器,继承了文本的解码方式:

01 package com.a2.desktop.example10.mina.statemachine;
02  
03 import java.nio.charset.Charset;
04 import java.util.LinkedList;
05  
06 import org.apache.mina.core.buffer.IoBuffer;
07 import org.apache.mina.core.filterchain.IoFilter.NextFilter;
08 import org.apache.mina.core.session.IoSession;
09 import org.apache.mina.filter.codec.ProtocolDecoderOutput;
10 import org.apache.mina.filter.codec.textline.LineDelimiter;
11 import org.apache.mina.filter.codec.textline.TextLineDecoder;
12  
13 public class CommandDecoder extends TextLineDecoder {
14  
15      public CommandDecoder() {
16             super(Charset.forName("UTF8"), LineDelimiter.WINDOWS);
17         }
18          
19         private Object parseCommand(String line) throws CommandSyntaxException {
20             String[] temp = line.split(" +"2);

你可能感兴趣的:(nio,telnet,Mina,LinkedList,StateMachine)