此文分析AsyncWeb如何和Mina的IoHandler结合的
一般的mina server类:
主类如下:
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
acceptor.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new TextLineCodecFactory(Charset
.forName("UTF-8"))));
acceptor.setHandler(new TimeServerHandler());
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
acceptor.bind(new InetSocketAddress(8080));
TimeServerHandler类如下:
public class TimeServerHandler extends IoHandlerAdapter {
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
cause.printStackTrace();
}
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
String str = message.toString();
System.out.println("Message read:");
System.out.println(str);
Date date = new Date();
session.write(date.toString());
System.out.println("Message written...");
session.close();
}
@Override
public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
System.out.println("IDLE " + session.getIdleCount(status));
}
}
一般的流程:初始化NioSocketAcceptor——》增加Filter——》设置Handler——》设置session属性——》bind()就可以了。启动后,通过TimeServerHandler从IoHandlerAdapter 里面的继承的方法,处理数据。
Asyncweb中的方式:
MinaTransport类中的start()
package org.apache.asyncweb.server.transport.mina
public void start() throws TransportException {
ioHandler = new DefaultHttpIoHandler();
ioHandler.setContainer( container );
acceptor = new NioSocketAcceptor(ioThreads);
eventExecutor = new OrderedThreadPoolExecutor(this.eventThreads);
boolean success = false;
try {
DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
chain.addFirst("threadPool", new ExecutorFilter(eventExecutor));
acceptor.setReuseAddress(true);
acceptor.getSessionConfig().setReuseAddress(true);
chain.addLast("mdc", new MdcInjectionFilter());
if (isLoggingTraffic) {
LOG.debug("Configuring traffic logging filter");
LoggingFilter filter = new LoggingFilter();
filter.setSessionClosedLogLevel(logLevel);
filter.setExceptionCaughtLogLevel(logLevel);
filter.setMessageReceivedLogLevel(logLevel);
filter.setMessageSentLogLevel(logLevel);
filter.setSessionClosedLogLevel(logLevel);
filter.setSessionCreatedLogLevel(logLevel);
filter.setSessionIdleLogLevel(logLevel);
filter.setSessionOpenedLogLevel(logLevel);
acceptor.getFilterChain().addLast("logging", filter);
}
// TODO make this configurable instead of hardcoding like this
acceptor.setBacklog(100);
acceptor.setHandler(ioHandler);
if (address != null) {
acceptor.bind(new InetSocketAddress(address, port));
} else {
acceptor.bind(new InetSocketAddress(port));
}
success = true;
LOG.debug("NIO HTTP Transport bound on port " + port);
} catch (IOException e) {
throw new TransportException("NIOTransport Failed to bind to port "
+ port, e);
} finally {
if (!success) {
acceptor.dispose();
acceptor = null;
}
}
}
package org.apache.asyncweb.server.transport.mina;
public class DefaultHttpIoHandler extends SingleSessionIoHandlerDelegate implements HttpIoHandler
{
/** the default idle time in seconds - 5 minutes */
public static final int DEFAULT_IDLE_TIME = 300;
public DefaultHttpIoHandler()
{
super( new Factory() );//父类的构造函数,参数必须实现SingleSessionIoHandlerFactory 这个接口
}
//实现了HttpIoHandler 里的setContainer()
public ServiceContainer getContainer()
{
return ( ( Factory ) getFactory() ).getContainer();
}
public void setContainer( ServiceContainer container )
{
( ( Factory ) getFactory() ).setContainer( container );
}
public void setReadIdle( int idleTime )
{
( ( Factory ) getFactory() ).setReadIdle( idleTime );
}
//生成SingleSessionIoHandler的工厂方法,而SingleSessionIoHandler是用来处理特定session的。
private static class Factory implements SingleSessionIoHandlerFactory
{
private ServiceContainer container;
private int readIdleTime = DEFAULT_IDLE_TIME;
public ServiceContainer getContainer()
{
return container;
}
public void setContainer( ServiceContainer container )
{
this.container = container;
}
public void setReadIdle( int idleTime )
{
this.readIdleTime = idleTime;
}
实现了SingleSessionIoHandlerFactory 的getHandler方法,
public SingleSessionIoHandler getHandler( IoSession session )
{
SingleHttpSessionIoHandler handler = new SingleHttpSessionIoHandler( container, session );
handler.setReadIdleTime( readIdleTime );
return handler;
}
}
}
类图:
总结:通过DefaultHttpIoHandler的处理,最终生成了IoHandler的实现类SingleHttpSessionIoHandler,
其中包含3个摄入的对象ServiceContainer,IoSession,readIdleTime。
数据的处理都是通过Filter的责任链来处理。
因为先要解析Http,并跳转到正确的HttpService。
下期预告:《AsyncWeb原理分析(四)——http的解析》