游乐游手机版
首页/AI教程/文章详情

SpringBoot项目整合Netty开发实战教程

时间:2026-08-14 21:14
Netty 是 JBoss 推出的一款 Java 开源网络通信框架,核心定位是为各类网络应用提供异步、事件驱动的编程模型。通俗来说,它是一套帮助开发者快速搭建高性能、高可用网络服务端与客户端的开发工具。作为基于 NIO 的开发框架,Netty 大幅简化了网络编程流程,不管是基于 TCP、UDP 的

Netty 是 JBoss 推出的一款 Java 开源网络通信框架,核心定位是为各类网络应用提供异步、事件驱动的编程模型。通俗来说,它是一套帮助开发者快速搭建高性能、高可用网络服务端与客户端的开发工具。作为基于 NIO 的开发框架,Netty 大幅简化了网络编程流程,不管是基于 TCP、UDP 的 Socket 通信,还是 FTP、SMTP、HTTP 等复杂二进制或文本协议的实现,都可以借助 Netty 更高效地完成开发。需要强调的是,Netty 所追求的“开发快速”和“使用简单”,并不是以牺牲性能为代价。凭借优秀的架构设计,Netty 在开发效率、系统性能、稳定性以及可扩展性之间实现了良好的平衡,因此也成为 Java 网络编程中非常常用的技术方案。

本文将带领大家学习如何在SpringBoot项目中集成Netty

一、Netty服务端

由于这里是 SpringBoot 项目示例,因此 SpringBoot 相关依赖不再单独展开说明。

1、导入依赖

org.projectlomboklombokio.nettynetty-all4.1.36.Final

2、编写netty处理器

/** * Socket拦截器,用于处理客户端的行为 * * @author Gjing **/@Slf4jpublic class SocketHandler extends ChannelInboundHandlerAdapter {public static final ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);/** * 读取到客户端发来的消息 * * @param ctx ChannelHandlerContext * @param msg msg * @throws Exception e */@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {// 由于我们配置的是 字节数组 编解码器,所以这里取到的用户发来的数据是 byte数组byte[] data = (byte[]) msg;log.info("收到消息: "   new String(data));// 给其他人转发消息for (Channel client : clients) {if (!client.equals(ctx.channel())) {client.writeAndFlush(data);}}}@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {log.info("新的客户端链接:"   ctx.channel().id().asShortText());clients.add(ctx.channel());}@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {clients.remove(ctx.channel());}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.channel().close();clients.remove(ctx.channel());}}

3、编写netty初始化器

/** * Socket 初始化器,每一个Channel进来都会调用这里的 InitChannel 方法 * @author Gjing **/@Componentpublic class SocketInitializer extends ChannelInitializer {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {ChannelPipeline pipeline = socketChannel.pipeline();// 添加对byte数组的编解码,netty提供了很多编解码器,你们可以根据需要选择pipeline.addLast(new ByteArrayDecoder());pipeline.addLast(new ByteArrayEncoder());// 添加上自己的处理器pipeline.addLast(new SocketHandler());}}

4、编写netty服务

/** * @author Gjing **/@Slf4j@Componentpublic class SocketServer {@Resourceprivate SocketInitializer socketInitializer;@Getterprivate ServerBootstrap serverBootstrap;/** * netty服务监听端口 */@Value("${netty.port:8088}")private int port;/** * 主线程组数量 */@Value("${netty.bossThread:1}")private int bossThread;/** * 启动netty服务器 */public void start() {this.init();this.serverBootstrap.bind(this.port);log.info("Netty started on port: {} (TCP) with boss thread {}", this.port, this.bossThread);}/** * 初始化netty配置 */private void init() {// 创建两个线程组,bossGroup为接收请求的线程组,一般1-2个就行NioEventLoopGroup bossGroup = new NioEventLoopGroup(this.bossThread);// 实际工作的线程组NioEventLoopGroup workerGroup = new NioEventLoopGroup();this.serverBootstrap = new ServerBootstrap();this.serverBootstrap.group(bossGroup, workerGroup) // 两个线程组加入进来.channel(NioServerSocketChannel.class)// 配置为nio类型.childHandler(this.socketInitializer); // 加入自己的初始化器}}

5、启动netty

因为当前使用的是 SpringBoot,所以我们可以在项目启动完成后自动触发 Netty 服务启动。也就是说,只要 SpringBoot 应用成功启动,Netty 服务器就会一并运行。

/** * 监听Spring容器启动完成,完成后启动Netty服务器 * @author Gjing **/@Componentpublic class NettyStartListener implements ApplicationRunner {@Resourceprivate SocketServer socketServer;@Overridepublic void run(ApplicationArguments args) throws Exception {this.socketServer.start();}}
效果图

image.png

二、Netty客户端

客户端部分这里使用 NIO 来实现,因此不再继续用 Netty 编写。实际开发中,很多场景都是 Netty 作为服务端,而客户端可能是 WebSocket 或普通 Socket。本文为了便于理解,就以 Socket 客户端为例进行演示。由于 NIO 是 Java 原生提供的能力,所以无需额外引入依赖。

1、编写客户端线程

由于不能阻塞主线程,因此需要额外开启一个子线程来处理客户端监听逻辑。

/** * @author Gjing **/public class ClientThread implements Runnable{private final Selector selector;public ClientThread(Selector selector) {this.selector = selector;}@Overridepublic void run() {try {for (; ; ) {int channels = selector.select();if (channels == 0) {continue;}Set selectionKeySet = selector.selectedKeys();Iterator keyIterator = selectionKeySet.iterator();while (keyIterator.hasNext()) {SelectionKey selectionKey = keyIterator.next();// 移除集合当前得selectionKey,避免重复处理keyIterator.remove();if (selectionKey.isReadable()) {this.handleRead(selector, selectionKey);}}}} catch (IOException e) {e.printStackTrace();}}// 处理可读状态private void handleRead(Selector selector, SelectionKey selectionKey) throws IOException {SocketChannel channel = (SocketChannel) selectionKey.channel();ByteBuffer byteBuffer = ByteBuffer.allocate(1024);StringBuilder message = new StringBuilder();if (channel.read(byteBuffer) > 0) {byteBuffer.flip();message.append(StandardCharsets.UTF_8.decode(byteBuffer));}// 再次注册到选择器上,继续监听可读状态channel.register(selector, SelectionKey.OP_READ);System.out.println(message);}}

2、客户端逻辑

/** * 聊天客户端 * * @author Gjing **/public class ChatClient {public void start(String name) throws IOException {SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8088));socketChannel.configureBlocking(false);Selector selector = Selector.open();socketChannel.register(selector, SelectionKey.OP_READ);// 监听服务端发来得消息new Thread(new ClientThread(selector)).start();// 监听用户输入Scanner scanner = new Scanner(System.in);while (scanner.hasNextLine()) {String message = scanner.nextLine();if (StringUtils.hasText(message)) {socketChannel.write(StandardCharsets.UTF_8.encode(name   ": "   message));}}}}

3、客户端1

/** * @author Gjing **/public class Client1 {public static void main(String[] args) throws IOException {new ChatClient().start("李四");}}

4、客户端2

/** * @author Gjing **/public class Client2 {public static void main(String[] args) throws IOException {new ChatClient().start("张三");}}

5、启动这两个客户端

image.png

此时服务端日志也会打印对应信息,说明已经成功监听到客户端接入。

image.png
rip|imageView2/2/w/1240)

接下来我们通过客户端2发送一条消息进行测试。

image.png

可以看到,客户端1已经成功收到了客户端2发送的消息。同样地,我们也可以通过客户端1继续发送消息进行验证。

image.png

与此同时,服务端也会同步输出对应的消息日志。

image.png

本文到这里就结束了。以上就是一个基于 SpringBoot 集成 Netty 的入门小案例,适合快速理解 Netty 服务端与 Socket 客户端通信的基本流程。更多进阶知识,大家可以前往 Netty 官方文档继续学习,Demo源代码地址:SpringBoot-Netty

来源:https://developer.aliyun.com/article/706893
上一篇GitHub Trending 太多看不完?用 WorkBuddy 自动聚合每日技术热点 下一篇AI智能体中专家与专家团的区别解析
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
CAD零基础入门教程:坐标输入、图层管理与基础绘图命令
AI教程 · 2026-09-01

CAD零基础入门教程:坐标输入、图层管理与基础绘图命令

本文面向CAD零基础学习者,系统讲解坐标输入、图层管理与基础绘图命令的核心用法。通过分步实操与常见问题排查,帮助新手建立精确绘图习惯,掌握规范出图的基础能力。

CAD从入门到项目交付:绘图、标注、图块与实战工作流
AI教程 · 2026-09-01

CAD从入门到项目交付:绘图、标注、图块与实战工作流

掌握CAD的核心在于建立“画得准、标得清、复用快、交付稳”的工作流。本文提供从环境设置、高频命令组合、标注规范、图块标准化到项目分阶段交付的完整路径,帮助初学者避免常见返工陷阱,独立完成可检查、可复用、可打印的工程图纸。

Claude Code 登录指南:个人、Teams 与企业账号区分与授权步骤
AI教程 · 2026-09-01

Claude Code 登录指南:个人、Teams 与企业账号区分与授权步骤

本文详细解析 Claude Code 登录前的账号类型区分方法,涵盖个人订阅、Teams 席位与企业 Enterprise 席位的授权路径差异。提供终端登录命令、环境变量排查及常见异常处理步骤,帮助用户快速完成正确授权并避免登录路径混淆。

Claude Code 文件修改前的权限模式配置与命令审批指南
AI教程 · 2026-09-01

Claude Code 文件修改前的权限模式配置与命令审批指南

本文详细介绍Claude Code在修改文件前的权限模式配置方法,包括defaultMode可选值、permissions allow与deny规则设置、多层级配置文件管理以及 status验证技巧,帮助开发者安全高效地使用AI编程助手。

Claude Code接入VS Code后先测扩展和终端命令
AI教程 · 2026-09-01

Claude Code接入VS Code后先测扩展和终端命令

在VS Code中接入Claude Code后,建议优先验证扩展面板与集成终端两条入口。本文提供标准检查顺序、关键命令与常见故障排查路径,帮助你快速确认环境就绪,避免后续开发受阻。