- 实例要求:使用IDEA 创建Netty项目
- Netty 服务器在 6668 端口监听,浏览器发出请求
"http://localhost:6668/ " - 服务器可以回复消息给客户端 "Hello! 我是服务器 5 " , 并
对特定请求资源进行过滤. - 目的:Netty 可以做Http服务开发,并且理解Handler实例
和客户端及其请求的关系.
package com.atguigu.netty.NettyHttp;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class HTTPServer {
public static void main(String[] args) throws Exception{
//1. 创建两个线程组 bossGroup 和 workerGroup
//2. bossGroup 只是处理连接请求 , 真正的和客户端业务处理,会交给 workerGroup完成
//3. 两个都是无限循环
//4. bossGroup 和 workerGroup 含有的子线程(NioEventLoop)的个数
// 默认实际 cpu核数 * 2
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup(); //8
try {
//2.创建服务器端的启动对象,配置参数
ServerBootstrap serverBootStrap = new ServerBootstrap();
//3.设置线程组
serverBootStrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new HTTPServerInitializer());
System.out.println("HTTP 服务器启动成功");
//4.绑定端口号
ChannelFuture channelFuture = serverBootStrap.bind(1192).sync();
//5.监听事件关闭
channelFuture.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
HTTPServerInitializer 通道初始化对象
创建一个通道初始化对象 并给WorkGroup的 EventLoop 对应的管道设置处理器 可以是Netty提供的 也可以是自定义的
package com.atguigu.netty.NettyHttp; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpServerCodec; public class HTTPServerInitializer extends ChannelInitializerHttp ServerHandle{ @Override protected void initChannel(SocketChannel ch) throws Exception { //向管道加入处理器 //得到管道 ChannelPipeline pipeline = ch.pipeline(); //加入netty提供的HttpServerCodec ; code =》 coder - decoder //netty 提供的处理http的编解码器 pipeline.addLast("my http server codec",new HttpServerCodec()); //增加自定义的处理器Handle pipeline.addLast("自定义Handler",new HTTPServerHandle()); } }
package com.atguigu.netty.NettyHttp; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.*; import io.netty.util.CharsetUtil; public class HTTPServerHandle extends SimpleChannelInboundHandler{ @Override protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { //判断msg是不是一个HttpRequest请求 if (msg instanceof HttpObject){ System.out.println("msg 类型="+ msg.getClass()); System.out.println("客户端地址="+ ctx.channel().remoteAddress()); //回复信息给浏览器 得做成Http协议的形式 //创建bytebuf ByteBuf cotent = Unpooled.copiedBuffer(" ByteBuf cotent = Unpooled.copiedBuffer("我是服务器返回消息", CharsetUtil.UTF_8);n", CharsetUtil.UTF_8); //构造一个http的响应 httpResponse 参数:1.协议版本 2.响应状态码3.内容 FullHttpResponse httpResponse = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.OK, cotent); //设置内容类型 httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain"); //设置返回数据长度 httpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH,cotent.readableBytes()); //将构建好的httpResponse 返回 ctx.writeAndFlush(httpResponse); } } }
服务启动后访问监听的浏览器端口即可得到返回消息
此时控制台打印
HTTP 服务器启动成功 客户端地址=/0:0:0:0:0:0:0:1:60504 客户端地址=/0:0:0:0:0:0:0:1:60504 客户端地址=/0:0:0:0:0:0:0:1:60505 客户端地址=/0:0:0:0:0:0:0:1:60505 客户端地址=/0:0:0:0:0:0:0:1:60509 客户端地址=/0:0:0:0:0:0:0:1:60509 客户端地址=/0:0:0:0:0:0:0:1:60510 客户端地址=/0:0:0:0:0:0:0:1:60510
会发现浏览器发送了两次请求
一次是请求网站,一次是请求网站的图标
进行请求过滤
//获取到消息
HttpRequest httpRequest = (HttpRequest) msg;
//获取uri 统一资源定位
URI uri = new URI(httpRequest.uri());
//如果uri的path路径包含请求图标
if ("/favicon.ico".equals(uri.getPath())){
System.out.println("请求了图标资源,不做相应");
return;
}



