1.声明
当前内容主要为本人学习netty,用来记录学习过程和问题
主要内容为:实现一个简单的访问响应的http服务器!
- 主要采用netty内置的
HttpRequestDecoder和HttpResponseEncoder
来实现加码和解码 - 采用自定义的
NettyHttpServerHandler
来实现响应的写出
2.demo
1.服务器类:NettyHttpServer
/**
*
* @author hy
* @createTime 2021-04-24 10:05:25
* @description 一个典型的netty的http服务器
*
*/
public class NettyHttpServer implements Startable {
private final int port;
private final EventLoopGroup parentGroup;
private final EventLoopGroup childGroup;
private final ServerBootstrap serverBootstrap;
public NettyHttpServer(int port) {
this.port = port;
this.parentGroup = new NioEventLoopGroup();
this.childGroup = new NioEventLoopGroup();
serverBootstrap = new ServerBootstrap();
}
@Override
public void start() throws InterruptedException {
try {
serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024);
serverBootstrap
.group(parentGroup, childGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new NettyHttpServerChannelInitializer());
Channel ch = serverBootstrap.bind(port).sync().channel();
System.out.println("当前服务器启动在:http://localhost:" + port+"/");
ch.closeFuture().sync();
}finally {
parentGroup.shutdownGracefully();
childGroup.shutdownGracefully();
}
}
}
2.初始化当前的pipeline的类
/**
*
* @author hy
* @createTime 2021-04-24 10:03:57
* @description 当前的netty http服务器的Channel初始化操作
*
*/
public class NettyHttpServerChannelInitializer
extends/* ChannelInitializer<SocketChannel> */ ChannelInitializer<Channel> {
@Override
protected void initChannel(Channel ch) throws Exception {
// TODO Auto-generated method stub
ch.pipeline()
/* .addLast(new HttpServerCodec()) */
/* .addLast(new HttpServerExpectContinueHandler()) */
.addLast(new HttpRequestDecoder()) // 客户端传递数据解码
.addLast(new NettyHttpServerHandler())
.addLast(new HttpResponseEncoder()) ;// 响应客户端数据加码
}
}
3.实际处理响应类
/**
*
* @author hy
* @createTime 2021-04-24 10:21:33
* @description 一个服务器端的http处理器
*
*/
public class NettyHttpServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println("连接上了客户端!");
}
byte[] content = "{\"msg\":\"你好netty世界!\"}".getBytes(CharsetUtil.UTF_8);
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// TODO Auto-generated method stub
System.out.println(msg);
// 每次接受到都直接响应..
if (msg instanceof HttpRequest) {
HttpRequest req = (HttpRequest) msg;
boolean keepAlive = HttpUtil.isKeepAlive(req);
FullHttpResponse response = new DefaultFullHttpResponse(req.protocolVersion(), HttpResponseStatus.OK,
Unpooled.wrappedBuffer(content));
response.headers()
// 设置当前的响应头content-type =application/json;charset=utf-8
.set(HttpHeaderNames.CONTENT_TYPE, "application/json;charset=utf-8")
// 设置当前的响应头部content-length
.setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
ctx.channel().writeAndFlush(response);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("出现异常.............");
cause.printStackTrace();
}
}
3.基本测试
响应成功!
4.其中出现的问题
1.浏览器一直转动,但是没有响应数据:就是必须调用ctx.channel().writeAndFlush(response);,不要调用write方法
2.传递响应内容数据必须使用:DefaultFullHttpResponse这个类
,并且必须在创建的时候指定数据(ByteBuf类型,使用Unpooled.wrappedBuffer(content)将字节转换为ByteBuf
)
5.总结
1.通过编写一个netty版的http服务器,很容易,并且也有很多坑