一、讲解
1、Netty服务在6669端口监听,浏览器发出请求"http://localhost://6669"
2、服务器可以回复消息,并对特定的资源进行过滤
3、目的:Netty可以做http服务开发,并且理解Handler实例和客户端及其请求的关系。
二、代码
package com.hao.netty.http;
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;
/**
* @author haoxiansheng
* @date 2020-05-24
*/
public class ServerTest {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.childHandler(new ServerInitializerTest());
//
ChannelFuture channelFuture = serverBootstrap.bind(6669).sync();
channelFuture.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
package com.hao.netty.http;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;
/**
* @author haoxiansheng
* @date 2020-05-24
*/
public class ServerInitializerTest extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
// 向管道假如处理器
// 得到管带
ChannelPipeline pipeline = socketChannel.pipeline();
/**
* 加入一个netty 提供的httpServerCodes => [coder decoder] 编=解码器
* 1、HttpServerCodec 是netty 提供的处理http的编解码器
* 2、增加一个自定义的编解码器
*/
pipeline.addLast("MyHttpServerCodec", new HttpServerCodec());
pipeline.addLast("MyHttpServerHandlerTest", new HttpServerHandlerTest());
}
}
package com.hao.netty.http;
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;
import java.net.URI;
/**
* @author haoxiansheng
* @date 2020-05-24
* @Description
* 1、SimpleChannelInboundHandler 继承 ChannelInboundHandlerAdapter
* 2、HttpObject 客户端和服务端相互通讯的数据被封装成HttpObject
*/
public class HttpServerHandlerTest extends SimpleChannelInboundHandler<HttpObject> {
/**
* <p>读取客户端数据<p/>
* @param ctx
* @param msg
* @throws Exception
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
// 判断msg 是不是HttpRequest请求
if (msg instanceof HttpRequest) {
System.out.println("msg 类型 ==> " + msg.getClass());
System.out.println("客户端的地址 =>" + ctx.channel().remoteAddress());
// 获取到http请求
HttpRequest httpRequest = (HttpRequest) msg;
// 获取uri, 过滤指定的资源
URI uri = new URI(httpRequest.uri());
if ("/favicon.ioc".equals(uri.getPath())) {
System.out.println("请求了 /favicon.ioc , 不做响应");
return;
}
// 回复信息给浏览器 【Http协议】
ByteBuf content = Unpooled.copiedBuffer("hello 我是服务你", CharsetUtil.UTF_8);
// 构造一个http的响应 即HttpResponse 父类接收
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
// 将构建好response 返回
ctx.writeAndFlush(response);
}
}
}