首页  

netty http server 实例     所属分类 netty 浏览量 68
netty 4.1.42.Final

server.HttpServer
server.HttpServerHandler
public interface RequestHandler {
    Object handle(FullHttpRequest fullHttpRequest);
}

handler.GetRequestHandler
handler.PostRequestHandler

private static final int DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt("io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));



@Slf4j public class HttpServer { private static final int PORT = 8080; public void start() { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) // TCP默认开启 Nagle 算法,尽可能的发送大数据快,减少网络传输 // TCP_NODELAY 参数的作用就是控制是否启用 Nagle 算法。 .childOption(ChannelOption.TCP_NODELAY, true) // 是否开启 TCP 底层心跳机制 .childOption(ChannelOption.SO_KEEPALIVE, true) // 用于临时存放已完成三次握手的请求的队列的最大长度,如果连接建立频繁,服务器处理创建新连接较慢,可以适当调大该参数 .option(ChannelOption.SO_BACKLOG, 128) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast("decoder", new HttpRequestDecoder()) .addLast("encoder", new HttpResponseEncoder()) .addLast("aggregator", new HttpObjectAggregator(512 * 1024)) .addLast("handler", new HttpServerHandler()); } }); Channel ch = b.bind(PORT).sync().channel(); log.info("Netty Http Server started on port {}.", PORT); ch.closeFuture().sync(); } catch (InterruptedException e) { log.error("occur exception when start server:", e); } finally { log.error("shutdown bossGroup and workerGroup"); bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
@Slf4j public class HttpServerHandler extends SimpleChannelInboundHandler< FullHttpRequest> { private static final String FAVICON_ICO = "/favicon.ico"; private static final AsciiString CONNECTION = AsciiString.cached("Connection"); private static final AsciiString KEEP_ALIVE = AsciiString.cached("keep-alive"); private static final AsciiString CONTENT_TYPE = AsciiString.cached("Content-Type"); private static final AsciiString CONTENT_LENGTH = AsciiString.cached("Content-Length"); @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) { log.info("Handle http request:{}", fullHttpRequest); String uri = fullHttpRequest.uri(); if (uri.equals(FAVICON_ICO)) { return; } RequestHandler requestHandler = RequestHandlerFactory.create(fullHttpRequest.method()); Object result; FullHttpResponse response; try { result = requestHandler.handle(fullHttpRequest); String responseHtml = "" + result + ""; byte[] responseBytes = responseHtml.getBytes(StandardCharsets.UTF_8); response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(responseBytes)); response.headers().set(CONTENT_TYPE, "text/html; charset=utf-8"); response.headers().setInt(CONTENT_LENGTH, response.content().readableBytes()); } catch (IllegalArgumentException e) { e.printStackTrace(); String responseHtml = "" + e+"" + ""; byte[] responseBytes = responseHtml.getBytes(StandardCharsets.UTF_8); response = new DefaultFullHttpResponse(HTTP_1_1, INTERNAL_SERVER_ERROR, Unpooled.wrappedBuffer(responseBytes)); response.headers().set(CONTENT_TYPE, "text/html; charset=utf-8"); } boolean keepAlive = HttpUtil.isKeepAlive(fullHttpRequest); if (!keepAlive) { ctx.write(response).addListener(ChannelFutureListener.CLOSE); } else { response.headers().set(CONNECTION, KEEP_ALIVE); ctx.write(response); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } @Override public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } }
@Slf4j public class GetRequestHandler implements RequestHandler { @Override public Object handle(FullHttpRequest fullHttpRequest) { String requestUri = fullHttpRequest.uri(); Map queryParameterMappings = this.getQueryParams(requestUri); return queryParameterMappings.toString(); } private Map getQueryParams(String uri) { QueryStringDecoder queryDecoder = new QueryStringDecoder(uri, Charsets.toCharset(CharEncoding.UTF_8)); Map> parameters = queryDecoder.parameters(); Map queryParams = new HashMap<>(); for (Map.Entry> attr : parameters.entrySet()) { for (String attrVal : attr.getValue()) { queryParams.put(attr.getKey(), attrVal); } } return queryParams; } }
@Slf4j public class PostRequestHandler implements RequestHandler { @Override public Object handle(FullHttpRequest fullHttpRequest) { String requestUri = fullHttpRequest.uri(); log.info("request uri :[{}]", requestUri); String contentType = this.getContentType(fullHttpRequest.headers()); if (contentType.equals("application/json")) { return fullHttpRequest.content().toString(Charsets.toCharset(CharEncoding.UTF_8)); } else { throw new IllegalArgumentException("only receive application/json type data"); } } private String getContentType(HttpHeaders headers) { String typeStr = headers.get("Content-Type"); String[] list = typeStr.split(";"); return list[0]; } }
get http://127.0.0.1:8080/hello?id=1&name=tiger {name=tiger, id=1} post http://127.0.0.1:8080/hello hello {"id":1,"name":"tiger"}
https://gitee.com/dyyx/work2024/tree/master/demo/nettydemo/http-server 基于netty的RESTFUL框架 基于netty的 简单 rpc 框架 ChannelPipeline和ChannelInitializer

上一篇     下一篇
MQTT与WebSocket

WebSocket通信过程及原理

websocket 聊天室简单例子

netty 趣事

Netty ChannelPipeline Inbound Outbound

netty 架构原理简介