Spring4+mina配置

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

 

转载于:https://my.oschina.net/jinniu/blog/743020

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值