多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## 一、Http 建立在TCP传输协议之上的应用层协议,目前主流针对于WEB开发,Http协议应用非常广泛 ,因此掌握HTTP协议的开发之重要。Netty如何基于Http协议进行开发,那么使用Netty的Http 协议也是异步非阻塞的。 ### Http协议的特点: 简单:客户端请求服务器时只需要指定URL和携带的参数 灵活:Http协议允许传输任意类型的数据对象,传输内容有Http消息头中的Content-Type加以标记 ### Http协议的组成 请求行 请求头 请求正文 ### Http协议 响应状态种类 1xx :提示消息。表示请求已经接受继续处理 2xx :成功 表示请求已经接受成功 3xx :重定向 要完成的请求必须进行进一步的操作 4xx :客户端错误。可能是请求语法错误或者请求无法实现 5xx: 服务器错误。服务器未能处理请求(可能内部出现异常) ### 常见相应状态码 200 ok 成功 400 bad Request 错误请求语法,不能被服务理解 401 Unauthorized 请求未经授权 403 Forbidden 服务器收到请求,但是请求被服务器拒绝 404 Not Found 请求资源不存在 405 Method Not Allowed 请求方式不被允许,如只支持get请求,但客户端使用post 请求 500 Inernal Server Error: 服务器发送不可预期的错误 503 Servr Unavailable:服务器当前不能处理客户端的请求,一段时间后可能才能恢复正常 ## 二、Netty与Http ### HttpHelloWorldServer 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(); } } } ### HttpHelloWorldServerInitializer 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 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(); } }