Apache Mina Server 是一个网络通信应用框架,为开发高性能和高可用性的网络应用程序提供了非常便利的框架。

特点:异步的NIO框架,将UDP当成"面向连接"的协议

一、组件管理

Mina的底层依赖的主要是Java NIO库,上层提供的是基于事件的异步接口
(1)IoService(最底层[起点])
作用:隐藏底层IO的细节,对上提供统一的基于事件的异步IO接口
IOSocketAcceptor和IOSocketChannel,分别对应TCP协议下的服务端和客户端的IOService,low-level IO经过IOService层后变成IO Event
(2)IoProcessor
作用:负责检查是否有数据在通道上读写
IoProcessor 负责调用注册在IoService 上的过滤器,并在过滤器链之后调用IoHandler
(3)IoFilter(拦截器[关键])
作用:日志输出、黑名单过滤、数据的编码(write 方向)与解码(read 方向)等功能
(4)IoHandler(业务逻辑处理[终点])
作用:接收、发送数据
每个IoService都需要指定一个IoHandler
(5)IoSession
作用:是对底层连接(服务器与客户端的特定连接,该连接由服务器地址、端口以及客户端地址、端口来决定)的封装

二、服务端流程:

1、通过SocketAcceptor 同客户端建立连接;
2、连接建立之后 I/O的读写交给了I/O Processor线程,I/O Processor是多线程的;
3、通过I/O Processor 读取的数据经过IoFilterChain里所有配置的IoFilter,IoFilter进行消息的过滤,格式的转换,在这个层面可以制定一些自定义的协议;
4、最后IoFilter将数据交给 Handler  进行业务处理,完成了整个读取的过程;
写入过程也是类似,只是刚好倒过来,通过IoSession.write 写出数据,然后Handler进行写入的业务处理,处理完成后交给IoFilterChain,进行消息过滤和协议的转换,最后通过 I/O Processor 将数据写出到 socket 通道

三、服务端代码实现

1、编写IoService(主要功能:设置过滤器,设置handler,绑定端口)

public class MinaServer {
private static Logger logger = Logger.getLogger(MinaServer.class);
public static void main(String[] args) {
Configuration config = Configuration.getInstance();
try {
config.readConfiguration();
config.initDataSource();
config.initServiceDef(); // 启动FTP读文件,PE积分后台执行
//此处为内部逻辑,通过FTP读取文件,跳过
} catch (Exception e1) {
e1.printStackTrace();
System.exit(1);
}
try {
config.initInterfaceConfig();
// 启动接口调用互斥map维护线程
InterfaceBusThread interfaceBusThread = new InterfaceBusThread();
interfaceBusThread.start();
} catch (Exception e) {
logger.info("InterfaceBus error!", e);
} NioSocketAcceptor acceptor = null; // 创建连接
try {
// 创建一个非阻塞的server端的Socket
acceptor = new NioSocketAcceptor(Runtime.getRuntime()
.availableProcessors() + 1);// ioprocesser线程数,一般为cpu数量+1 // 建立工作线程池
Executor threadPool = Executors.newFixedThreadPool(Constant.threadCount);// 设置20个handler线程 // 解决在LINUX服务器上kill掉了,但是端口仍然被占用,要过一段时间才能释放
acceptor.setReuseAddress(true); // 添加消息过滤器
acceptor.getFilterChain().addLast("codec",
new ProtocolCodecFilter(new XMLObjectCodecFactory()));
//
// 设置服务器能够接收的最大连接数
acceptor.setBacklog(Constant.maxSocketConn);
acceptor.getFilterChain().addLast("executor",
new ExecutorFilter(threadPool));
// 设置读取数据的缓冲区大小
acceptor.getSessionConfig().setReadBufferSize(2048);
// 读写通道10秒内无操作进入空闲状态
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
// 绑定逻辑处理器
acceptor.setHandler(new MinaServerHandler()); // 添加业务处理
// 绑定端口
acceptor.bind(new InetSocketAddress(Constant.minaServerPort));
logger.info("server start success... port:"
+ Constant.minaServerPort); } catch (Exception e) {
logger.error("server start error....", e);
e.printStackTrace();
System.exit(1);
}
}
}

2、编写过滤器(即上面代码的添加消息过滤器,这里使用了Mina自带的换行符编解码器工厂,注意:要在acceptor.bind()方法之前执行)

3、编写IoHandler

public class MinaServerHandler extends IoHandlerAdapter {
private final static Logger log = LoggerFactory.getLogger(TCPServerHandler.class); @Override
public void messageReceived(IoSession session, Object message) throws Exception {
//业务代码在这里编写处理
String str = message.toString();
System.out.println("The message received is [" + str + "]");
if (str.endsWith("quit")) {
session.close(true);
return;
}
} @Override
public void sessionCreated(IoSession session) throws Exception {
System.out.println("server session created");
super.sessionCreated(session);
} @Override
public void sessionOpened(IoSession session) throws Exception {
System.out.println("server session Opened");
super.sessionOpened(session);
} @Override
public void sessionClosed(IoSession session) throws Exception {
System.out.println("server session Closed");
super.sessionClosed(session);
} }

4、将IoHandler 注册到IoService(即上面代码的绑定逻辑处理器,注意:要在acceptor.bind()方法之前执行)

5、运行MinaServer中的main 方法,可以看到控制台一直处于阻塞状态,等待客户端连接

四、Maven的pom.xml配置

<!-- MINA集成 -->
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-integration-spring</artifactId>
<version>1.1.7</version>
</dependency>

五、测试类(模拟客户端请求)

public class AutoTest {
private final static String IP = "localhost";
private final static int PORT = 9002;
public static void main(String[] args) {
String msg = "<root><check>testEquityInsertRev</check><method>equityinsertrev</method><param><usernumber>13632599010</usernumber><equityid>1</equityid><statedate>20130620</statedate></param></root>";
System.out.println("testEquityInsertRev request msg:"+msg);
System.out.println("testEquityInsertRev response msg:"+testApi(msg));
}

Mina框架(实战详解)的更多相关文章

  1. NHibernate实战详解(二)映射配置与应用

    关于NHibernate的资料本身就不多,中文的就更少了,好在有一些翻译文章含金量很高,另外NHibernate与Hibernate的使用方式可谓神似,所以也有不少经验可以去参考Hibernate. ...

  2. 《iOS 7 应用开发实战详解》

    <iOS 7 应用开发实战详解> 基本信息 作者: 朱元波    管蕾 出版社:人民邮电出版社 ISBN:9787115343697 上架时间:2014-4-25 出版日期:2014 年5 ...

  3. Android安卓书籍推荐《Android驱动开发与移植实战详解》下载

    百度云下载地址:点我 Android凭借其开源性.优异的用户体验和极为方便的开发方式,赢得了广大用户和开发者的青睐,目前已经发展成为市场占有率很高的智能手机操作系统. <Android驱动开发与 ...

  4. Java SPI机制实战详解及源码分析

    背景介绍 提起SPI机制,可能很多人不太熟悉,它是由JDK直接提供的,全称为:Service Provider Interface.而在平时的使用过程中也很少遇到,但如果你阅读一些框架的源码时,会发现 ...

  5. 《Android NFC 开发实战详解 》简介+源码+样章+勘误ING

    <Android NFC 开发实战详解>简介+源码+样章+勘误ING SkySeraph Mar. 14th  2014 Email:skyseraph00@163.com 更多精彩请直接 ...

  6. 011-Scala中的apply实战详解

    011-Scala中的apply实战详解 object中的apply方法 class中的apply方法 使用方法 apply方法可以应用在类或者Object对象中 class类 必须要创建实例化的类对 ...

  7. 010-Scala单例对象、伴生对象实战详解

    010-Scala单例对象.伴生对象实战详解 Scala单例对象详解 函数的最后一行是返回值 子项目 Scala伴生对象代码实战 object对象的私有成员可以直接被class伴生类访问,但是不可以被 ...

  8. 008-Scala主构造器、私有构造器、构造器重载实战详解

    008-Scala主构造器.私有构造器.构造器重载实战详解 Scala主构造器实战 无参数的主构造器 分析 1.name 需要赋初值,一般通过占位符来代表空值 2.private 声明私有的age 生 ...

  9. 009-Scala的内部类实战详解

    009-Scala的内部类实战详解 Scala内部类详解 与java的区别 java的内部类是从属于外部类的 Scala的内部类是从属于对象的 内部类在调用方法的时候传递的内部类只能是由自己本身 欢迎 ...

随机推荐

  1. NSData 与 struct 以及XML的转换。

    在做OC与C++ 混编的时候,我们可能会用到struct 与NSData的相互转换.在这里做一个记录 1.struct转换为NSData 例如如下的struct: struct tagPackageH ...

  2. c#一些特殊语法

    1.using 语法 using不仅可以作为导入包,重命名类名.还可以释放资源 using (Pen gridLinePen = new Pen(Color.red)) { e.Graphics.Dr ...

  3. [RDLC]一步一步教你使用RDLC(一)

    一:加数据集,并且命名为Quotation,如下图所示: 二: 添加一张报表,命名为Quotation,如下图所示: 向报表中添加"表"这一项,如下图所示: 这时就弹出一个选择数据 ...

  4. 深入理解Android IPC机制之Binder机制

    Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有的进程间通信IPC手段包括(Internet Process Connection): 管道(Pipe).信号(Sign ...

  5. 【翻译】Ext JS最新技巧——2014-8-13

    原文:Top Support Tips Greg Barry:新的框架. 新的文档类型(Doctype) 在Ext JS 5,只支持IE8+,因此不再古力用户使用严格的HTML文档类型.现在,推荐使用 ...

  6. Ext JS 5初探(三)

    在上文提到了本地化文件的问题,然后在Ext JS 5的包里找了找,居然还没包含本地化包.我估计目前还不到考虑本地化的时候.在Sencha Touch中,是没有本地化包的,但是要让Ext JS也不包含本 ...

  7. TinySpring分析二

    step5 看完了前面的几步,到现在我们必然要想到的问题就是,数据要是放在xml中怎么读? 其实按照正常思维一步一步来,从xml中读数据和之前手工配进去并没有什么大的区别,只要读出来就OK了. 先看测 ...

  8. ReentrantReadWriteLock读写锁的使用2

    本文可作为传智播客<张孝祥-Java多线程与并发库高级应用>的学习笔记. 这一节我们做一个缓存系统. 在读本节前 请先阅读 ReentrantReadWriteLock读写锁的使用1 第一 ...

  9. C语言实现牛顿迭代法解方程

    利用迭代算法解决问题,需要做好以下三个方面的工作: 一.确定迭代变量 在可以用迭代算法解决的问题中,我们可以确定至少存在一个可直接或间接地不断由旧值递推出新值的变量,这个变量就是迭代变量. 二.建立迭 ...

  10. iOS8 UILocalNotification 增加启动授权

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/46810357 ...