此文分析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 {@Overridepublic void exceptionCaught(IoSession session, Throwable cause) throws Exception { cause.printStackTrace();}@Overridepublic 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();}@Overridepublic 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.minapublic 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 thisacceptor.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的Factory 方法,而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的解析》