关于Apache Mina一、介绍MINA(Multipurpose Infrastructure for Network Applications)是用于开发高性能和高可用性的网络应用程序的基础框架。
通过使用MINA框架可以可以省下处理底层I/O和线程并发等复杂工作,开发人员能够把更多的精力投入到业务设计和开发当中。
MINA框架的应用比较广泛,应用的开源项目有Apache Directory、AsyncWeb、Apache Qpid、QuickFIX/J、Openfire、SubEthaSTMP、red5等。
MINA框架的特点有:基于java NIO类库开发;采用非阻塞方式的异步传输;事件驱动;支持批量数据传输;支持TCP、UDP协议;控制反转的设计模式(支持Spring);采用优雅的松耦合架构;可灵活的加载过滤器机制;单元测试更容易实现;可自定义线程的数量,以提高运行于多处理器上的性能;采用回调的方式完成调用,线程的使用更容易。
二、调用过程在图中的模块链中,IoService 便是应用程序的入口,相当于代码中的 IoAccepter,IoAccepter 便是 IoService 的一个扩展接口。
IoService 接口可以用来添加多个 IoFilter,这些 IoFilter 符合责任链模式并由 IoProcessor 线程负责调用。
而 IoAccepter 在 ioService 接口的基础上还提供绑定某个通讯端口以及取消绑定的接口。
在上图中最右端也就是 IoHandler,这便是业务处理模块。
在业务处理类中不需要去关心实际的通讯细节,只管处理客户端传输过来的信息即可。
编写 Handler 类就是使用 MINA 开发网络应用程序的重心所在,相当于 MINA 已经帮你处理了所有的通讯方面的细节问题。
为了简化 Handler 类,MINA 提供了 IoHandlerAdapter 类,此类仅仅是实现了 IoHandler 接口,但并不做任何处理。
IoHandler 接口中具有如下一些方法:Java代码1.public interface IoHandler {2. void sessionCreated(IoSession session) throws Exception;//会话创建3. void sessionOpened(IoSession session) throws Exception;//打开会话,与sessionCreated最大的区别是它是从另一个线程处调用的4. void sessionClosed(IoSession session) throws Exception;//会话结束,当连接关闭时被调用5. void sessionIdle (IoSession session, IdleStatus status) throws Exception;//会话空闲6. void exceptionCaught(IoSession session, Throwable cause) throws Exception;//异常捕获,Mina会自动关闭此连接7. void messageReceived(IoSession session, Object message) throws Exception;//接收到消息8. void messageSent(IoSession session, Object message) throws Exception;//发送消息9.}IoService 是负责底层通讯接入,而 IoHandler 是负责业务处理的。
那么 MINA 架构图中的IoFilter 作何用途呢?答案是你想作何用途都可以。
但是有一个用途却是必须的,那就是作为IoService 和 IoHandler 之间的桥梁。
IoHandler 接口中最重要的一个方法是 messageReceived,这个方法的第二个参数是一个 Object 型的消息,众所周知,Object 是所有 Java 对象的基础,那到底谁来决定这个消息到底是什么类型呢?答案也就在这个 IoFilter 中。
在下面使用的例子中,我们添加了一个 IoFilter 是 new ProtocolCodecFilter(new TextLineCodecFactory()),这个过滤器的作用是将来自客户端输入的信息转换成一行行的文本后传递给 IoHandler,因此我们可以在messageReceived 中直接将 msg 对象强制转换成 String 对象。
而如果我们不提供任何过滤器的话,那么在 messageReceived 方法中的第二个参数类型就是一个 byte 的缓冲区,对应的类是 mon.ByteBuffer。
虽然你也可以将解析客户端信息放在 IoHandler 中来做,但这并不是推荐的做法,使原来清晰的模型又模糊起来,变得IoHandler 不只是业务处理,还得充当协议解析的任务。
MINA自身带有一些常用的过滤器,例如LoggingFilter(日志记录)、BlackListFilter(黑名单过滤)、CompressionFilter(压缩)、SSLFilter(SSL加密)等。
三、使用示例1.服务器端Java代码1.package com.logcd.mina2;2.3.import java.io.IOException;4.import .InetSocketAddress;5.import java.nio.charset.Charset;6.7.import org.apache.mina.core.service.IoAcceptor;8.import org.apache.mina.filter.codec.ProtocolCodecFilter;9.import org.apache.mina.filter.codec.textline.TextLineCodecFactory;10.import org.apache.mina.filter.logging.LoggingFilter;11.import org.apache.mina.transport.socket.nio.NioSocketAcceptor;12.13./**14. * 服务端主程序15. */16.public class MinaServer{17.18. private static final int PORT = 8901;// 定义监听端口19.20. public static void main(String[] args) throws IOException21. {22. // 创建服务端监控线程23. IoAcceptor acceptor = new NioSocketAcceptor();24. // 设置日志记录器25. acceptor.getFilterChain().addLast("logger", new LoggingFilter());26. // 设置编码过滤器27. acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));28. // 指定业务逻辑处理器29. acceptor.setHandler(new ServerHandler());30. // 设置端口号31. acceptor.setDefaultLocalAddress(new InetSocketAddress(PORT));32. // 启动监听线程33. acceptor.bind();34. }35.}Java代码1.package com.logcd.mina2;2.3.import org.apache.mina.core.service.IoHandlerAdapter;4.import org.apache.mina.core.session.IoSession;5.6./**7. * 服务端逻辑控制类8. */9.public class ServerHandler extends IoHandlerAdapter{10.11. @Override12. /**13. * 连接创建事件14. */15. public void sessionCreated(IoSession session)16. {17. // 显示客户端的ip和端口18. System.out.println(session.getRemoteAddress().toString());19. }20.21. @Override22. /**23. * 消息接收事件24. */25. public void messageReceived(IoSession session, Object message) throws Exception26. {27. String str = message.toString();28. if (str.trim().equalsIgnoreCase("quit"))29. {30. // 结束会话31. session.close(true);32. return;33. }34. // 返回消息字符串35. session.write("Hi Client!");36. // 打印客户端传来的消息内容37. System.out.println("Message written..." + str);38. }39.}2.客户端Java代码1.package com.logcd.mina2;2.3.import .InetSocketAddress;4.import java.nio.charset.Charset;5.6.import org.apache.mina.core.future.ConnectFuture;7.import org.apache.mina.filter.codec.ProtocolCodecFilter;8.import org.apache.mina.filter.codec.textline.TextLineCodecFactory;9.import org.apache.mina.filter.logging.LoggingFilter;10.import org.apache.mina.transport.socket.nio.NioSocketConnector;11.12./**13. * 客户端主程序14. */15.public class MinaClient16.{17.18. public static void main(String[] args)19. {20. // 创建客户端连接器.21. NioSocketConnector connector = new NioSocketConnector();22. // 设置日志记录器23. connector.getFilterChain().addLast("logger", new LoggingFilter());24. // 设置编码过滤器25. connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(newTextLineCodecFactory(Charset.forName("UTF-8"))));26. // 设置连接超时检查时间27. connector.setConnectTimeoutCheckInterval(30);28. // 设置事件处理器29. connector.setHandler(new ClientHandler());30. // 建立连接31. ConnectFuture cf = connector.connect(new InetSocketAddress("195.2.199.170", 8901));32. // 等待连接创建完成33. cf.awaitUninterruptibly();34. // 发送消息35. cf.getSession().write("Hi Server!");36. // 发送消息37. cf.getSession().write("quit");38. // 等待连接断开39. cf.getSession().getCloseFuture().awaitUninterruptibly();40. // 释放连接41. connector.dispose();42. }43.}Java代码1.package com.logcd.mina2;2.3.import org.apache.mina.core.service.IoHandlerAdapter;4.import org.apache.mina.core.session.IoSession;5.6./**7. * 客户端逻辑控制类8. */9.public class ClientHandler extends IoHandlerAdapter {10.11. @Override12. /**13. * 消息接收事件14. */15. public void messageReceived(IoSession session, Object message)16. throws Exception {17. System.out.println("server message:" + message.toString());// 显示接收到的消息18. }19.}。