关于Netty--Http请求处理方式
作者:BtWangZhi
这篇文章主要介绍了关于Netty--Http请求处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
Netty--Http请求处理
1.这几天在看Netty权威指南,代码敲了一下,就当做个笔记吧。
/** * Http服务端 * @author Tang * 2018年5月13日 */ public class HttpServer { public void run(String url,Integer port) { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup); bootstrap.channel(NioServerSocketChannel.class); bootstrap.childHandler(new ChannelInitializer<Channel>() { @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline().addLast("http-decoder", new HttpRequestDecoder()); ch.pipeline().addLast("http-aggregator", new HttpObjectAggregator(65536)); ch.pipeline() .addLast("http-encoder", new HttpResponseEncoder()); ch.pipeline() .addLast("http-chunked", new ChunkedWriteHandler()); ch.pipeline().addLast("http-handler", new HttpServerHandler()); } }); try { ChannelFuture channelFuture = bootstrap.bind(url, port).sync(); channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) { new HttpServer().run("127.0.0.1",8001); } }
业务处理逻辑
public class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> { @Override protected void messageReceived(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) throws Exception { // 构造返回数据 JSONObject jsonRootObj = new JSONObject(); JSONObject jsonUserInfo = new JSONObject(); jsonUserInfo.put("id", 1); jsonUserInfo.put("name", "张三"); jsonUserInfo.put("password", "123"); jsonRootObj.put("userInfo", jsonUserInfo); // 获取传递的数据 Map<String, Object> params = getParamsFromChannel(ctx, fullHttpRequest); jsonRootObj.put("params", params); FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK); response.headers().set(CONTENT_TYPE, "application/json; charset=UTF-8"); StringBuilder bufRespose = new StringBuilder(); bufRespose.append(jsonRootObj.toJSONString()); ByteBuf buffer = Unpooled.copiedBuffer(bufRespose, CharsetUtil.UTF_8); response.content().writeBytes(buffer); buffer.release(); ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); } /** * 获取传递的参数 * * @param ctx * @param fullHttpRequest * @return * @throws UnsupportedEncodingException */ private static Map<String, Object> getParamsFromChannel( ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) throws UnsupportedEncodingException { HttpHeaders headers = fullHttpRequest.headers(); String strContentType = headers.get("Content-Type").trim(); System.out.println("ContentType:" + strContentType); Map<String, Object> mapReturnData = new HashMap<String, Object>(); if (fullHttpRequest.getMethod() == HttpMethod.GET) { // 处理get请求 QueryStringDecoder decoder = new QueryStringDecoder( fullHttpRequest.getUri()); Map<String, List<String>> parame = decoder.parameters(); for (Entry<String, List<String>> entry : parame.entrySet()) { mapReturnData.put(entry.getKey(), entry.getValue().get(0)); } System.out.println("GET方式:" + parame.toString()); } else if (fullHttpRequest.getMethod() == HttpMethod.POST) { // 处理POST请求 if (strContentType.contains("x-www-form-urlencoded")) { HttpPostRequestDecoder decoder = new HttpPostRequestDecoder( new DefaultHttpDataFactory(false), fullHttpRequest); List<InterfaceHttpData> postData = decoder.getBodyHttpDatas(); for (InterfaceHttpData data : postData) { if (data.getHttpDataType() == HttpDataType.Attribute) { MemoryAttribute attribute = (MemoryAttribute) data; mapReturnData.put(attribute.getName(), attribute.getValue()); } } } else if (strContentType.contains("application/json")) { // 解析json数据 ByteBuf content = fullHttpRequest.content(); byte[] reqContent = new byte[content.readableBytes()]; content.readBytes(reqContent); String strContent = new String(reqContent, "UTF-8"); System.out.println("接收到的消息" + strContent); JSONObject jsonParamRoot = JSONObject.parseObject(strContent); for (String key : jsonParamRoot.keySet()) { mapReturnData.put(key, jsonParamRoot.get(key)); } } else { FullHttpResponse response = new DefaultFullHttpResponse( HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR); ctx.writeAndFlush(response).addListener( ChannelFutureListener.CLOSE); } System.out.println("POST方式:" + mapReturnData.toString()); } return mapReturnData; } }
支持Get和PostContentType为application/json、x-www-form-urlencoded的处理。
用Postman亲测无问题。
Netty处理简单Http请求的例子
废话不多说 上代码
HttpHelloWorldServerInitializer.java
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.ssl.SslContext; public class HttpHelloWorldServerInitializer extends ChannelInitializer<SocketChannel> { private final SslContext sslCtx; public HttpHelloWorldServerInitializer(SslContext sslCtx) { this.sslCtx = sslCtx; } @Override public void initChannel(SocketChannel ch) { ChannelPipeline p = ch.pipeline(); if (sslCtx != null) { p.addLast(sslCtx.newHandler(ch.alloc())); } p.addLast(new HttpServerCodec()); p.addLast(new HttpHelloWorldServerHandler()); } }
HttpHelloWorldServerHandler.java
import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpHeaderUtil; import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpRequest; import static io.netty.handler.codec.http.HttpHeaderNames.*; import static io.netty.handler.codec.http.HttpResponseStatus.*; import static io.netty.handler.codec.http.HttpVersion.*; public class HttpHelloWorldServerHandler extends ChannelHandlerAdapter { private static final byte[] CONTENT = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' }; @Override public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { if (msg instanceof HttpRequest) { HttpRequest req = (HttpRequest) msg; if (HttpHeaderUtil.is100ContinueExpected(req)) { ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE)); } boolean keepAlive = HttpHeaderUtil.isKeepAlive(req); FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(CONTENT)); response.headers().set(CONTENT_TYPE, "text/plain"); response.headers().setInt(CONTENT_LENGTH, response.content().readableBytes()); if (!keepAlive) { ctx.write(response).addListener(ChannelFutureListener.CLOSE); } else { response.headers().set(CONNECTION, HttpHeaderValues.KEEP_ALIVE); ctx.write(response); } } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } }
HttpHelloWorldServer.java
import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.util.SelfSignedCertificate; /** * An HTTP server that sends back the content of the received HTTP request * in a pretty plaintext form. */ public final class HttpHelloWorldServer { static final boolean SSL = System.getProperty("ssl") != null; static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080")); public static void main(String[] args) throws Exception { // Configure SSL. final SslContext sslCtx; if (SSL) { SelfSignedCertificate ssc = new SelfSignedCertificate(); sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey()); } else { sslCtx = null; } // Configure the server. EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.option(ChannelOption.SO_BACKLOG, 1024); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new HttpHelloWorldServerInitializer(sslCtx)); Channel ch = b.bind(PORT).sync().channel(); System.err.println("Open your web browser and navigate to " + (SSL? "https" : "http") + "://127.0.0.1:" + PORT + '/'); ch.closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。