先来进行一下相关名词解释:
Netty
Netty是构建在Java NIO之上的一个强大的网络编程框架,它通过其灵活的Channel机制支持多种协议,包括WebSocket,能够高效地开发出高性能的网络应用程序,简化了NIO的使用,同时提供了对WebSocket等现代网络协议的支持。
Channel
在Netty中,Channel是Java NIO的一个核心概念,代表一个开放的连接或者绑定到一个特定设备的开放连接,比如一个硬件设备、一个文件、一个网络套接字等。Channel提供了一种与底层操作系统交互的方法,允许数据在网络或文件系统之间传输。通过使用Channel,可以执行读取和写入操作,而不需要直接处理流。
WebSocket
WebSocket是一种应用层通信协议,提供了全双工通信通道,可以在单个TCP连接上进行双向数据传输。WebSocket协议使得客户端和服务器之间的消息交换更加简单,允许服务器主动向客户端推送数据。这种特性非常适合需要实时更新的应用场景,如在线游戏、聊天应用等。
NIO
NIO是Java提供的面向块的I/O操作的一种方式,NIO引入了几个新的抽象概念,如Buffer、Channel和Selector,它们共同作用以提高I/O效率,特别是在处理大量并发连接时。NIO支持非阻塞模式,线程可以在等待数据到来的同时做其他事情,从而提高资源利用率。
下面看一下具体的代码实现:
java
@Slf4j
@Component
public class NettyWebSocketServer {
private final int port = 8081;
private EventLoopGroup bossGroup;
private EventLoopGroup workerGroup;
private Channel serverChannel;
@PostConstruct
public void start() throws Exception {
log.info("Starting Netty WebSocket server on port {}", port);
bossGroup = new NioEventLoopGroup(1);
workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(port))
.childHandler(new NettyWebSocketInitializer());
serverChannel = b.bind().sync().channel();
log.info("Netty WebSocket server started successfully on ws://localhost:{}", port);
} catch (InterruptedException e) {
log.error("Failed to start Netty server", e);
Thread.currentThread().interrupt();
throw new RuntimeException("Netty server startup interrupted", e);
}
}
@PreDestroy
public void stop() {
log.info("Shutting down Netty WebSocket server...");
if (serverChannel != null) {
serverChannel.closeFuture().syncUninterruptibly();
}
if (bossGroup != null) {
bossGroup.shutdownGracefully().syncUninterruptibly();
}
if (workerGroup != null) {
workerGroup.shutdownGracefully().syncUninterruptibly();
}
log.info("Netty WebSocket server shut down.");
}
}
java
@Component
public class NettyWebSocketInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new ChunkedWriteHandler());
pipeline.addLast(new HttpObjectAggregator(65536));
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
pipeline.addLast(new NettyWebSocketHandler());
}
}
java
@Slf4j
@Component
public class NettyWebSocketHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
private static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
@Override
public void handlerAdded(ChannelHandlerContext ctx) {
Channel channel = ctx.channel();
channels.add(channel);
log.info("Client connected: {}", channel.remoteAddress());
channels.writeAndFlush(new TextWebSocketFrame("[SERVER] User joined: " + formatTime()));
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) {
Channel channel = ctx.channel();
channels.remove(channel);
log.info("Client disconnected: {}", channel.remoteAddress());
channels.writeAndFlush(new TextWebSocketFrame("[SERVER] User left: " + formatTime()));
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) {
if (frame instanceof TextWebSocketFrame) {
String message = ((TextWebSocketFrame) frame).text();
log.info("Received message from {}: {}", ctx.channel().remoteAddress(), message);
String response = "[BROADCAST] " + formatTime() + " - " + message;
channels.writeAndFlush(new TextWebSocketFrame(response));
} else {
log.warn("Unsupported WebSocket frame type: {}", frame.getClass().getSimpleName());
ctx.disconnect();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
log.error("WebSocket error from {}", ctx.channel().remoteAddress(), cause);
ctx.close();
}
private String formatTime() {
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"));
}
}
启动项目后可用Postman进行测试:

看一下具体的核心类:
NettyWebSocketServer:Netty 服务的生命周期管理器
- 在 Spring 容器启动时启动 Netty 服务器
- 在 Spring 容器关闭时优雅地关闭 Netty
- 持有 EventLoopGroup和Channel 引用,用于资源释放
NettyWebSocketInitializer:初始化Channel
- 为每个新连接的客户端 构建 ChannelPipeline
- 添加编解码器、协议处理器、自定义 Handler
NettyWebSocketHandler:业务逻辑处理器(
- 处理 WebSocket 帧(如 TextWebSocketFrame)
- 实现消息广播、存储、私聊等业务
- 管理连接上线/下线(通过 handlerAdded / handlerRemoved)
请求处理流程:
- 应用启动 → Spring 创建NettyWebSocketServer → 调用start()
- Netty 启动 → 绑定端口,设置 childHandler = new NettyWebSocketInitializer()
- 客户端连接 → Netty 调用 NettyWebSocketInitializer.initChannel()
- Pipeline 构建 → 添加 Codec + ProtocolHandler + new NettyWebSocketHandler(service)
- WebSocket 握手 → WebSocketServerProtocolHandler自动处理 HTTP → WebSocket 升级
- 消息到达 → NettyWebSocketHandler.channelRead0()被调用 → 执行业务逻辑