写一个 Hello 服务器我这里主要是基于spring boot 2.6.9 依赖
spring-boot-starter-webflux 讲netty
Netty 实现的 Hello服务器都需要下面这些:
一个服务器
handler
:这个组件实现了服务器的业务逻辑,决定了连接创建后和接收到信
息后该如何处理
Bootstrapping
: 这个是配置服务器的启动代码。最少需要设置服务器绑定的端口,用来
监听连接请求。
通过
ChannelHandler
来实现服务器的逻辑
Hello
Server 将会将接受到的数据的拷贝发送给客户端。因此,我们需要实现
ChannelInboundHandler
接口,用来定义处理入站事件的方法。由于我们的应用很简单,只
需要继承
ChannelInboundHandlerAdapter
就行了。这个类 提供了默认
ChannelInboundHandler
的实现,所以只需要覆盖下面的方法:
channelRead() -
每个信息入站都会调用
channelReadComplete() -
通知处理器最后的
channelread()
是当前批处理中的最后一条
消息时调用
exceptionCaught()-
读操作时捕获到异常时调用
HelloServerHandler
代码如下:
package com.kais.nettylesson.lesson1;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.CharsetUtil;
import org.junit.jupiter.api.Test;
import java.net.InetSocketAddress;
//开启共享
@Sharable
public class HelloServerHandler extends ChannelInboundHandlerAdapter {
/**
* 调用{@link ChannelHandlerContextfireChannelRead(Object)}转发到{@link ChannelInboundHandler}中的下一个{@link ChannelInboundHandler}<p>
* 子类可以重写此方法以更改行为@param ctx@param msg
*
* @param ctx
* @param msg
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf in = (ByteBuf) msg;
System.out.println("收到的服务器: " + in.toString(CharsetUtil.UTF_8)); //2 ctx.write(in);
}
/**
* 调用{@link ChannelHandlerContextfireChannelReadComplete()}转发到{@link ChannelInboundHandler}中的下一个{@link ChannelInboundHandler}<p>
* 子类可以重写此方法以更改行为。
*
* @param ctx
*/
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
.addListener(ChannelFutureListener.CLOSE);
}
/**
* 调用{@link ChannelHandlerContextfireExceptionCaught(Throwable)}转发到{@link ChannelPipeline}中的下一个{@link ChannelHandler}<p>
* 子类可以重写此方法以更改行为@参数ctx@参数原因
*
* @param ctx
* @param cause
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
@Test
public void helloServerStart() throws Exception {
int port = 8001;
NioEventLoopGroup group = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(group)
.channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)).childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new HelloServerHandler());
}
});
ChannelFuture f = b.bind().sync();
System.out.println(HelloServerHandler.class.getName() + " 开始并收听 " + f.channel().localAddress());
f.channel().closeFuture().sync();
group.shutdownGracefully().sync();
}
}
访问http://127.0.0.1:8001/?123321213=123123
返回如下:
收到的服务器: GET /?123321213=123123 HTTP/1.1
User-Agent: PostmanRuntime/7.29.0
Accept: */*
Postman-Token: f788edb6-c66a-46f9-b42e-cca131eca028
Host: 127.0.0.1:8001
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
就成功了