大纲
- 构建一对主从线程组
- 定义服务器启动类
- 为服务器设置Channel
- 设置处理从线程池的助手类初始化器
- 监听启动和关闭服务器
步骤
- 新建Maven空项目,pom.xml添加Netty依赖;
<dependencies> <!-- https://mvnrepository.com/artifact/io.netty/netty-all --> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.25.Final</version> </dependency> </dependencies>
- 建立启动类HelloServer.java;
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; /** * @Description: 服务器启动类,实现客户端发送一个请求,服务器会返回 hello netty */ public class HelloServer { public static void main(String[] args) throws Exception { //定义两个线程池(线程组) //主线程组,用于接受客户端的连接,不做任何处理 EventLoopGroup bossGroup =new NioEventLoopGroup() ; //从线程组,接受主线程组抛出的任务 EventLoopGroup wokerGroup =new NioEventLoopGroup() ; try { //netty服务器的创建,ServerBootstrap是一个启动类 ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup,wokerGroup) //设置主从线程组 .channel(NioServerSocketChannel.class) //设置nio双向通道 .childHandler(null); //子处理器,用于处理wokerGroup //用于启动server,并且设置端口,设置启动方式为同步 ChannelFuture channelFuture = serverBootstrap.bind(8088).sync(); //监听关闭channel,设置为同步方式 channelFuture.channel().closeFuture().sync(); } finally { //优雅关闭 bossGroup.shutdownGracefully(); wokerGroup.shutdownGracefully(); } } }
- 设置子处理器Channel(初始化器);
- 建立一个初始化器HelloServerInitializer.java ;
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpServerCodec; /** * @Description: 这是一个初始化器,当channle注册后,会执行里面相应的初始化方法 */ public class HelloServerInitializer extends ChannelInitializer<SocketChannel> { protected void initChannel(SocketChannel channel) throws Exception { //通过channel获取对应的管道pipeline ChannelPipeline pipeline = channel.pipeline(); //通过管道pipeline添加handler pipeline.addLast("HttpServerCodec",new HttpServerCodec()) //HttpServerCodec是Netty自己提供的助手类,请求到服务端时解码,响应到客户端时编码 .addLast("customHandler",null) //添加自定义的助手类 功能待添加 ; } }
- 修改启动类HelloServer.java,将子处理器声明为刚刚建立的初始化器;
serverBootstrap.group(bossGroup,wokerGroup) //设置主从线程组 .channel(NioServerSocketChannel.class) //设置nio双向通道 .childHandler(new HelloServerInitializer()); //子处理器,用于处理wokerGroup,功能在初始化器中定义
- 创建自定义的助手类CustomHandler.java;
import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.*; import io.netty.util.CharsetUtil; /** * @Description: 自定义助手类 */ //SimpleChannelInboundHandler:对于请求来讲,相当于入站 public class CustomHandler extends SimpleChannelInboundHandler<HttpObject> { protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { //获取Channel Channel channel = ctx.channel(); if (msg instanceof HttpRequest) { //显示客户端你的远程地址 System.out.println(channel.remoteAddress()); //定义发送的数据消息 ByteBuf content = Unpooled.copiedBuffer("Hello Netty!", CharsetUtil.UTF_8); //构建一个HttpResponse 1.1版本会默认开启一个长连接,效率会高过1.0 DefaultFullHttpResponse 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()); //把响应返回(刷)给客户端,先写后刷 ctx.writeAndFlush(response); } } }
- 将自定义的助手类声明到初始化类,修改HelloServerInitializer.java
//通过管道pipeline添加handler pipeline.addLast("HttpServerCodec",new HttpServerCodec()) //HttpServerCodec是Netty自己提供的助手类,请求到服务端时解码,响应到客户端时编码 .addLast("customHandler",new CustomHandler()) //添加自定义的助手类 ;
- 至此自定义助手类已经配置完毕;
- 建立一个初始化器HelloServerInitializer.java ;
- 启动HelloServer.java,运行main 方法开启Netty服务;
- 浏览器测试:http://localhost:8088/
- 测试结果:
- 完毕