1.spring配置
通过spring配置mina
<!-- mina -->
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.net.SocketAddress"
value="org.apache.mina.integration.beans.InetSocketAddressEditor">
</entry>
</map>
</property>
</bean>
<!-- 服务端handler -->
<bean id="imsHandler" class="cn.jn.core.mina.IMSHandler" />
<!-- 系统过滤器(自定义编码解码) -->
<bean id="codecFilter" class="org.apache.mina.filter.codec.ProtocolCodecFilter">
<constructor-arg>
<bean class="cn.jn.core.mina.IMSProtocalCodecFactory">
</bean>
</constructor-arg>
</bean>
<bean id="loggingFilter" class="org.apache.mina.filter.logging.LoggingFilter" />
<bean id="filterChainBuilder"
class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder">
<property name="filters">
<map>
<entry key="codecFilter" value-ref="codecFilter" />
<entry key="loggingFilter" value-ref="loggingFilter" />
</map>
</property>
</bean>
<!-- 服务端配置 -->
<bean id="ioAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor"
init-method="bind" destroy-method="unbind">
<property name="defaultLocalAddress" value=":9527" />
<property name="handler" ref="imsHandler" />
<property name="filterChainBuilder" ref="filterChainBuilder" />
<property name="reuseAddress" value="true" />
</bean>
<!-- session config 通过工厂方法注入 -->
<bean id="sessionConfig" factory-bean="ioAcceptor" factory-method="getSessionConfig">
<property name="bothIdleTime" value="10" />
<property name="minReadBufferSize" value="512" />
<property name="maxReadBufferSize" value="10240" />
</bean>
2.自定义编码过滤器
IMSProtocalCodecFactory编码工厂类
package cn.jn.core.mina;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder;
public class IMSProtocalCodecFactory implements ProtocolCodecFactory {
private final IMSProtocalEncoder encoder;
private final IMSProtocalDecoder decoder;
public IMSProtocalCodecFactory() {
encoder = new IMSProtocalEncoder();
decoder = new IMSProtocalDecoder();
}
public ProtocolEncoder getEncoder(IoSession session) {
return encoder;
}
public ProtocolDecoder getDecoder(IoSession session) {
return decoder;
}
}
IMSProtocalEncoder编码
package cn.jn.core.mina;
import java.nio.charset.Charset;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
public class IMSProtocalEncoder extends ProtocolEncoderAdapter {
@SuppressWarnings("unused")
private final Charset charset=Charset.forName("UTF-8");;
public IMSProtocalEncoder() {
super();
}
// 在此处实现包的编码工作,并把它写入输出流中
public void encode(IoSession session, Object message,
ProtocolEncoderOutput out) throws Exception {
String value = (String) message;
System.out.println("================================");
System.out.println(value);
System.out.println("================================");
IoBuffer buf = IoBuffer.allocate(value.getBytes().length);
buf.setAutoExpand(true);
if (value != null)
buf.put(value.trim().getBytes());
buf.flip();
out.write(buf);
}
}
IMSProtocalDecoder解码
前7位明文为后边密文的长度
package cn.jn.core.mina;
import org.apache.log4j.Logger;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
public class IMSProtocalDecoder implements ProtocolDecoder {
/**
* Logger for this class
*/
private static final Logger logger = Logger
.getLogger(IMSProtocalDecoder.class);
private final AttributeKey context = new AttributeKey(getClass(), "context");
private final Charset charset = Charset.forName("UTF-8");
// 请求报文最大长度100K
private int maxPackLength = 102400;
/**
* 构造方法
*
* @Title: IMSProtocalDecoder
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param:
* @throws
*/
public IMSProtocalDecoder() {
super();
}
public int getMaxLineLength() {
return maxPackLength;
}
public void setMaxLineLength(int maxLineLength) {
if (maxLineLength <= 0) {
throw new IllegalArgumentException("请求报文最大长度: " + maxLineLength);
}
this.maxPackLength = maxLineLength;
}
private Context getContext(IoSession session) {
Context ctx;
ctx = (Context) session.getAttribute(context);
if (ctx == null) {
ctx = new Context();
session.setAttribute(context, ctx);
}
return ctx;
}
public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
throws Exception {
// 报文前缀长度
final int packHeadLength = 7;
// 先获取上次的处理上下文,其中可能有未处理完的数据
Context ctx = getContext(session);
// 先把当前buffer中的数据追加到Context的buffer当中
ctx.append(in);
// 把position指向0位置,把limit指向原来的position位置
IoBuffer buf = ctx.getBuffer();
buf.flip();
// 然后按数据包的协议进行读取
while (buf.remaining() >= packHeadLength) {
buf.mark();
// 读取消息头部分
int length = buf.getInt();
// 检查读取是否正常,不正常的话清空buffer
if (length < 0 || length > maxPackLength) {
logger.warn("报文长度[" + length + "] 超过最大长度:" + maxPackLength
+ "或者小于0,清空buffer");
buf.clear();
break;
}
// 读取正常的消息,并写入输出流中,以便IoHandler进行处理
else if (length >= packHeadLength
&& length - packHeadLength <= buf.remaining()) {
int oldLimit = buf.limit();
buf.limit(buf.position() + length - packHeadLength);
String content = buf.getString(ctx.getDecoder());
buf.limit(oldLimit);
out.write(content);
} else {
// 如果消息包不完整,将指针重新移动消息头的起始位置
buf.reset();
break;
}
}
if (buf.hasRemaining()) {
// 将数据移到buffer的最前面
IoBuffer temp = IoBuffer.allocate(maxPackLength)
.setAutoExpand(true);
temp.put(buf);
temp.flip();
buf.clear();
buf.put(temp);
} else {// 如果数据已经处理完毕,进行清空
buf.clear();
}
}
public void finishDecode(IoSession session, ProtocolDecoderOutput out)
throws Exception {
}
public void dispose(IoSession session) throws Exception {
Context ctx = (Context) session.getAttribute(context);
if (ctx != null) {
session.removeAttribute(context);
}
}
// 记录上下文,因为数据触发没有规模,很可能只收到数据包的一半
// 所以,需要上下文拼起来才能完整的处理
private class Context {
private final CharsetDecoder decoder;
private IoBuffer buf;
private int matchCount = 0;
private int overflowPosition = 0;
private Context() {
decoder = charset.newDecoder();
buf = IoBuffer.allocate(3000).setAutoExpand(true);
}
public CharsetDecoder getDecoder() {
return decoder;
}
public IoBuffer getBuffer() {
return buf;
}
@SuppressWarnings("unused")
public int getOverflowPosition() {
return overflowPosition;
}
@SuppressWarnings("unused")
public int getMatchCount() {
return matchCount;
}
@SuppressWarnings("unused")
public void setMatchCount(int matchCount) {
this.matchCount = matchCount;
}
@SuppressWarnings("unused")
public void reset() {
overflowPosition = 0;
matchCount = 0;
decoder.reset();
}
public void append(IoBuffer in) {
getBuffer().put(in);
}
}
}