今天在阅读JetServer源码protocal部分的时候碰见了内部类的又一写法。定义一个接口LoginProtocol,包括了一个域和一个方法,然后在其中写了三个内部类,分别实现了该接口,代码如下:
package org.menacheri.jetserver.handlers.netty; import static org.menacheri.jetserver.event.Events.LOG_IN; import static org.menacheri.jetserver.event.Events.PROTCOL_VERSION; import static org.menacheri.jetserver.event.Events.RECONNECT; import java.util.List; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.ChannelHandler; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder; import org.jboss.netty.handler.codec.frame.LengthFieldPrepender; import org.jboss.netty.handler.codec.http.HttpChunkAggregator; import org.jboss.netty.handler.codec.http.HttpRequestDecoder; import org.jboss.netty.handler.codec.http.HttpResponseEncoder; import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; import org.menacheri.jetserver.event.Events; /** * Applies a protocol to the incoming pipeline which will handle login. * Subsequent protocol may also be manipulated by these login handlers. * * @author Abraham Menacherry * */ public interface LoginProtocol { String LOGIN_HANDLER_NAME = "loginHandler"; /** * Apply a protocol on the pipeline to handle login. Implementations will * first "search" if the incoming bytes correspond to the implementations * protocol, only if they match, the correspoinding protocol will be * applied. * * @param buffer * The incoming buffer, by default around 5 bytes will be read * and passed on to detect the protocol * @param pipeline * The channelpipeline on which the login protocol handlers need * to be set. * @return Returs true if the protocol was applied, else false. */ public boolean applyProtocol(ChannelBuffer buffer, ChannelPipeline pipeline); /** * Searches the incoming bytes of a client connection to determine if its an * HTTP connection, in which case Websocket or HTTP related handlers will be * applied on the piepline. * * @author Abraham Menacherry * */ public static class HTTPProtocol implements LoginProtocol { private WebSocketLoginHandler webSocketLoginHandler; @Override public boolean applyProtocol(ChannelBuffer buffer, ChannelPipeline pipeline) { boolean isThisProtocol = false; final int magic1 = buffer.getUnsignedByte(buffer.readerIndex()); final int magic2 = buffer.getUnsignedByte(buffer.readerIndex() + 1); if (isHttp(magic1, magic2)) { pipeline.addLast("decoder", new HttpRequestDecoder()); pipeline.addLast("aggregator", new HttpChunkAggregator(65536)); pipeline.addLast("encoder", new HttpResponseEncoder()); pipeline.addLast("handler", new WebSocketServerProtocolHandler("/jetsocket")); pipeline.addLast(LOGIN_HANDLER_NAME, webSocketLoginHandler); isThisProtocol = true; } return isThisProtocol; } /** * Method which checks if the first 2 incoming parameters are G, E or * similar combiantions which signal that its an HTTP protocol, since * some protocols like jetserver‘s default protocol send the length * first (which is 2 arbitrary bytes), its better if this protocol is * searched last to avoid switching to HTTP protocol prematurely. * * @param magic1 * @param magic2 * @return true if the two incoming bytes match any of the first two * letter of HTTP headers like GET, POST etc. */ protected boolean isHttp(int magic1, int magic2) { return magic1 == ‘G‘ && magic2 == ‘E‘ || // GET magic1 == ‘P‘ && magic2 == ‘O‘ || // POST magic1 == ‘P‘ && magic2 == ‘U‘ || // PUT magic1 == ‘H‘ && magic2 == ‘E‘ || // HEAD magic1 == ‘O‘ && magic2 == ‘P‘ || // OPTIONS magic1 == ‘P‘ && magic2 == ‘A‘ || // PATCH magic1 == ‘D‘ && magic2 == ‘E‘ || // DELETE magic1 == ‘T‘ && magic2 == ‘R‘ || // TRACE magic1 == ‘C‘ && magic2 == ‘O‘; // CONNECT } public WebSocketLoginHandler getWebSocketLoginHandler() { return webSocketLoginHandler; } public void setWebSocketLoginHandler(WebSocketLoginHandler webSocketLoginHandler) { this.webSocketLoginHandler = webSocketLoginHandler; } } /** * This is the default protocol of jetserver. If incoming event is of type * LOG_IN and also has appropriate protocol version as defined in the * {@link Events} class, then this protocol will be applied. The 3rd and 4th * bytes of the incoming transmission are searched to get this information. * * @author Abraham Menacherry * */ public static class DefaultJetProtocol implements LoginProtocol { private int frameSize = 1024; private EventDecoder eventDecoder; private LoginHandler loginHandler; private LengthFieldPrepender lengthFieldPrepender; @Override public boolean applyProtocol(ChannelBuffer buffer, ChannelPipeline pipeline) { boolean isThisProtocol = false; final int opcode = buffer.getUnsignedByte(buffer.readerIndex() + 2); final int protocolVersion = buffer.getUnsignedByte(buffer .readerIndex() + 3); if (isJetProtocol(opcode, protocolVersion)) { pipeline.addLast("framer", createLengthBasedFrameDecoder()); pipeline.addLast("eventDecoder", eventDecoder); pipeline.addLast(LOGIN_HANDLER_NAME, loginHandler); pipeline.addLast("lengthFieldPrepender", lengthFieldPrepender); isThisProtocol = true; } return isThisProtocol; } protected boolean isJetProtocol(int magic1, int magic2) { return ((magic1 == LOG_IN || magic1 == RECONNECT) && magic2 == PROTCOL_VERSION); } public ChannelHandler createLengthBasedFrameDecoder() { return new LengthFieldBasedFrameDecoder(frameSize, 0, 2, 0, 2); } public int getFrameSize() { return frameSize; } public void setFrameSize(int frameSize) { this.frameSize = frameSize; } public EventDecoder getEventDecoder() { return eventDecoder; } public void setEventDecoder(EventDecoder eventDecoder) { this.eventDecoder = eventDecoder; } public LoginHandler getLoginHandler() { return loginHandler; } public void setLoginHandler(LoginHandler loginHandler) { this.loginHandler = loginHandler; } public LengthFieldPrepender getLengthFieldPrepender() { return lengthFieldPrepender; } public void setLengthFieldPrepender( LengthFieldPrepender lengthFieldPrepender) { this.lengthFieldPrepender = lengthFieldPrepender; } } public static class CompositeProtocol implements LoginProtocol { private List<LoginProtocol> protocols; @Override public boolean applyProtocol(ChannelBuffer buffer, ChannelPipeline pipeline) { if (null != protocols) { for (LoginProtocol protocol : protocols) { if (protocol.applyProtocol(buffer, pipeline)) { return true; } } } return false; } public List<LoginProtocol> getProtocols() { return protocols; } public void setProtocols(List<LoginProtocol> protocols) { this.protocols = protocols; } } }
在用Spring框架进行注入的时候,引用的方法是:接口所在的包名.接口名.内部类名字:
<!-- Login Protocols these decide what handlers are in the pipeline during login of a client to jetserver --> <bean id="httpLoginProtocol" class="org.menacheri.jetserver.handlers.netty.LoginProtocol.HTTPProtocol" > <property name="webSocketLoginHandler" ref="webSocketLoginHandler" ></property> </bean> <bean id="defaultJetLoginProtocol" class="org.menacheri.jetserver.handlers.netty.LoginProtocol.DefaultJetProtocol" > <property name="eventDecoder" ref="eventDecoder"></property> <property name="loginHandler" ref="loginHandler"></property> <property name="lengthFieldPrepender" ref="lengthFieldPrepender"></property> </bean> <bean id="compositeLoginProtocol" class="org.menacheri.jetserver.handlers.netty.LoginProtocol.CompositeProtocol" scope="prototype"> <property name="protocols"> <list> <ref bean="defaultJetLoginProtocol"/> <ref bean="httpLoginProtocol"/> </list> </property> </bean>
时间: 2024-10-15 22:41:56