Netty实现HTTP服务器

Netty 本身就支持了 HTTP 协议,内置的 HttpServerCodec 可以针对 HTTP 协议进行编解码,开箱即用,非常方便。使用 Netty 来来实现一个简单的 HTTP 服务是非常简单的。

代码上传至 Gitee:https://gitee.com/panchanghe/netty-project


1. HttpServer

Http 服务的启动类,它主要是创建 ServerBootstrap 引导,让 Netty 服务可以跑起来。

public class HttpServer {
 private final int port;

 public HttpServer(int port) {
  this.port = port;
 }

 public static void main(String[] args) {
  new HttpServer(9999).start();
 }

 public void start() {
  EventLoopGroup boss = new NioEventLoopGroup(1);
  EventLoopGroup worker = new NioEventLoopGroup();
  new ServerBootstrap()
    .group(boss, worker)
    .channel(NioServerSocketChannel.class)
    .option(ChannelOption.SO_BACKLOG, 100)
    .childHandler(new HttpChannelInitializer())
    .localAddress(port)
    .bind()
;
 }
}

2. HttpChannelInitializer

ChannelHandler 的初始化类,当有新的客户端 Channel 接入时,它负责对 SocketChannel 的 Pipeline 进行初始化。

@ChannelHandler.Sharable
public class HttpChannelInitializer extends ChannelInitializer<SocketChannel{
 @Override
 protected void initChannel(SocketChannel sc) throws Exception {
  // HTTP协议编解码器
  sc.pipeline().addLast(new HttpServerCodec());
  // HTTP聚合器,得到一个完整的HTTP请求和响应
  sc.pipeline().addLast(new HttpObjectAggregator(1024 * 1024 * 10));
  // 文件分块传输
  sc.pipeline().addLast(new ChunkedWriteHandler());
  // HTTP请求分发器
  sc.pipeline().addLast(RequestDispatcher.INSTANCE);
 }
}

3. RequestDispatcher

请求分发器,这里实现的比较简单,只针对文件做简单的响应,如果文件不存在,返回 404 页面。

@ChannelHandler.Sharable
public class RequestDispatcher extends SimpleChannelInboundHandler<FullHttpRequest{
 public static RequestDispatcher INSTANCE = new RequestDispatcher();
 private static File BASE_FILE;
 static {
  BASE_FILE = new File(RequestDispatcher.class.getResource("/static").getFile());
 }

 @Override
 protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
  String uri = request.uri();
  if (uri.startsWith("/static")) {
   // 文件传输
   File diskFile = new File(BASE_FILE, uri.replace("/static/"""));
   if (diskFile.exists()) {
    writeFile(diskFile, ctx, request);
   }else {
    // 404
    write404(ctx, request);
   }
  }
 }

 // 404页
 private static void write404(ChannelHandlerContext ctx, FullHttpRequest request) {
  HttpResponse response = new DefaultHttpResponse(request.protocolVersion(), HttpResponseStatus.NOT_FOUND);
  ByteBuf buf = ctx.alloc().directBuffer().writeBytes("<h1>404</h1>".getBytes());
  response.headers().add(HttpHeaderNames.CONTENT_TYPE, "text/html");
  response.headers().add(HttpHeaderNames.CONTENT_LENGTH, buf.readableBytes());
  ctx.write(response);
  ctx.write(buf);
  ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
 }

 // 响应文件
 private static void writeFile(File diskFile, ChannelHandlerContext ctx, FullHttpRequest request) {
  try {
   // 文件传输
   HttpResponse response = new DefaultHttpResponse(request.protocolVersion(), HttpResponseStatus.OK);
   RandomAccessFile file = new RandomAccessFile(diskFile, "r");
   FileRegion fileRegion = new DefaultFileRegion(file.getChannel(), 0, file.length());
   response.headers().add(HttpHeaderNames.CONTENT_LENGTH, file.length());
   ctx.write(response);
   ctx.write(fileRegion);
   ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
  }catch (Exception e){
   e.printStackTrace();
  }
 }
}

4. 测试

我在网上找了一个网页模板,包含 Html、Css、Js,将它们放到项目的 static 目录下,就可以被访问到了。Netty实现HTTP服务器访问:http://127.0.0.1:9999/static/index.html即可看到效果了。Netty实现HTTP服务器

原文始发于微信公众号(程序员小潘):Netty实现HTTP服务器

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/29418.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!