A ChannelEvent is handled by a list of ChannelHandlers in a ChannelPipeline.The pipeline
implements an advanced form of the Intercepting Filter pattern to give a user full control over how an event
is handled and how the handlers in the pipeline interact with each other.
整体结构见图。
public class MyReadHandler implements SimpleChannelHandler { public void messageReceived(ChannelHandlerContext ctx, MessageEvent evt) { Object message = evt.getMessage(); // Do something with the received message. ... // And forward the event to the next handler. ctx.sendUpstream(evt); } }
/* * JBoss, Home of Professional Open Source * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.netty.example.http; import java.net.InetSocketAddress; import java.util.concurrent.Executors; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.ChannelFactory; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; /** * @author The Netty Project ([email protected]) * @author Andy Taylor ([email protected]) */ public class HttpServer { public static void main(String[] args) { // Configure the server. ChannelFactory factory = new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool()); ServerBootstrap bootstrap = new ServerBootstrap(factory); //[color=red]设置管道[/color] bootstrap.setPipelineFactory(new HttpServerPipelineFactory()); bootstrap.setOption("child.tcpNoDelay", true); bootstrap.setOption("child.keepAlive", true); // Bind and start to accept incoming connections. bootstrap.bind(new InetSocketAddress(8080)); } }
管道实现类
/* * JBoss, Home of Professional Open Source * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.netty.example.http; import static org.jboss.netty.channel.Channels.*; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.handler.codec.http.HttpRequestDecoder; import org.jboss.netty.handler.codec.http.HttpResponseEncoder; /** * @author The Netty Project ([email protected]) * @author Andy Taylor ([email protected]) */ public class HttpServerPipelineFactory implements ChannelPipelineFactory { public ChannelPipeline getPipeline() throws Exception { // Create a default pipeline implementation. ChannelPipeline pipeline = pipeline(); // Uncomment the following line if you want HTTPS //SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine(); //engine.setUseClientMode(false); //pipeline.addLast("ssl", new SslHandler(engine)); pipeline.addLast("decoder", new HttpRequestDecoder()); // Uncomment the following line if you don't want to handle HttpChunks. //pipeline.addLast("aggregator", new HttpChunkAggregator(1048576)); pipeline.addLast("encoder", new HttpResponseEncoder()); //[color=red]加入自定义handler[/color] pipeline.addLast("handler", new HttpRequestHandler()); return pipeline; } }
自定义handler类
/* * JBoss, Home of Professional Open Source * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.netty.example.http; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureListener; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelPipelineCoverage; import org.jboss.netty.channel.ExceptionEvent; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelUpstreamHandler; import org.jboss.netty.handler.codec.http.Cookie; import org.jboss.netty.handler.codec.http.CookieDecoder; import org.jboss.netty.handler.codec.http.CookieEncoder; import org.jboss.netty.handler.codec.http.DefaultHttpResponse; import org.jboss.netty.handler.codec.http.HttpChunk; import org.jboss.netty.handler.codec.http.HttpHeaders; import org.jboss.netty.handler.codec.http.HttpRequest; import org.jboss.netty.handler.codec.http.HttpResponse; import org.jboss.netty.handler.codec.http.HttpResponseStatus; import org.jboss.netty.handler.codec.http.HttpVersion; import org.jboss.netty.handler.codec.http.QueryStringDecoder; /** * @author The Netty Project ([email protected]) * @author Andy Taylor ([email protected]) */ @ChannelPipelineCoverage("one") public class HttpRequestHandler extends SimpleChannelUpstreamHandler { private volatile HttpRequest request; private volatile boolean readingChunks; private final StringBuilder responseContent = new StringBuilder(); @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { if (!readingChunks) { HttpRequest request = this.request = (HttpRequest) e.getMessage(); responseContent.append("WELCOME TO THE WILD WILD WEB SERVER\r\n"); responseContent.append("===================================\r\n"); responseContent.append("VERSION: " + request.getProtocolVersion().getText() + "\r\n"); if (request.containsHeader(HttpHeaders.Names.HOST)) { responseContent.append("HOSTNAME: " + request.getHeader(HttpHeaders.Names.HOST) + "\r\n"); } responseContent.append("REQUEST_URI: " + request.getUri() + "\r\n\r\n"); if (!request.getHeaderNames().isEmpty()) { for (String name: request.getHeaderNames()) { for (String value: request.getHeaders(name)) { responseContent.append("HEADER: " + name + " = " + value + "\r\n"); } } responseContent.append("\r\n"); } QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri()); Map<String, List<String>> params = queryStringDecoder.getParameters(); if (!params.isEmpty()) { for (Entry<String, List<String>> p: params.entrySet()) { String key = p.getKey(); List<String> vals = p.getValue(); for (String val : vals) { responseContent.append("PARAM: " + key + " = " + val + "\r\n"); } } responseContent.append("\r\n"); } if (request.isChunked()) { readingChunks = true; } else { ChannelBuffer content = request.getContent(); if (content.readable()) { responseContent.append("CONTENT: " + content.toString("UTF-8") + "\r\n"); } writeResponse(e); } } else { HttpChunk chunk = (HttpChunk) e.getMessage(); if (chunk.isLast()) { readingChunks = false; responseContent.append("END OF CONTENT\r\n"); writeResponse(e); } else { responseContent.append("CHUNK: " + chunk.getContent().toString("UTF-8") + "\r\n"); } } } private void writeResponse(MessageEvent e) { // Convert the response content to a ChannelBuffer. ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent.toString(), "UTF-8"); responseContent.setLength(0); // Decide whether to close the connection or not. boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request.getHeader(HttpHeaders.Names.CONNECTION)) || request.getProtocolVersion().equals(HttpVersion.HTTP_1_0) && !HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request.getHeader(HttpHeaders.Names.CONNECTION)); // Build the response object. HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); response.setContent(buf); response.setHeader(HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=UTF-8"); response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buf.readableBytes())); String cookieString = request.getHeader(HttpHeaders.Names.COOKIE); if (cookieString != null) { CookieDecoder cookieDecoder = new CookieDecoder(); Set<Cookie> cookies = cookieDecoder.decode(cookieString); if(!cookies.isEmpty()) { // Reset the cookies if necessary. CookieEncoder cookieEncoder = new CookieEncoder(true); for (Cookie cookie : cookies) { cookieEncoder.addCookie(cookie); } response.addHeader(HttpHeaders.Names.SET_COOKIE, cookieEncoder.encode()); } } // Write the response. ChannelFuture future = e.getChannel().write(response); // Close the connection after the write operation is done if necessary. if (close) { future.addListener(ChannelFutureListener.CLOSE); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { e.getCause().printStackTrace(); e.getChannel().close(); } }
需要进一步了解
杭州社区购物-滨江区西兴街道连园商铺李宁全场大优惠