之前写了一篇《IDEA插件开发之快速启动HTTP服务》提到了两种嵌入式HTTP服务的实现,后来想着既然是Java网络编程,那肯定是少不了大名鼎鼎的Netty。于是想着基于Netty以最小的代价实现一个http服务器。
netty官方带有一些常用的协议编码器,http就在其中,如果是编写服务器,则需要使用到HttpRequestDecoder 和HttpResponseEncoder,有一个HttpServerCodec类直接封装了这两个类。咱们还需要自行实现一个业务处理器,在这里先命名为HttpServerHandler吧。
然后直接上源码:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.*;
import java.nio.charset.StandardCharsets;
public class HttpServer {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup(5);
EventLoopGroup workerGroup = new NioEventLoopGroup(20);
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline()
.addLast(new HttpServerCodec())
.addLast(new HttpServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
try {
ChannelFuture channelFuture = bootstrap.bind(13388).sync();
channelFuture.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
private static class HttpServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof HttpRequest request) {
if ("/hello".equals(request.uri()) && request.method() == HttpMethod.GET) {
ByteBuf content = Unpooled.copiedBuffer("hello world".getBytes(StandardCharsets.UTF_8));
HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/html;charset=UTF-8") ;
response.headers().set(HttpHeaderNames.CONTENT_LENGTH,String.valueOf(content.readableBytes()));
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE) ;
}
}
}
}
}
直接启动后在浏览器中访问 http://localhost:13388/hello 则可看到一下内容:
这里还有另一个问题,就是https不是默认支持的,如果需要支持https,需要将对应的编码器添加到处理流水线中去。
可参见:netty 实现https服务器