SpringBoot整合Netty实现WebSocket的示例代码

 更新时间:2022年05月12日 15:49:32   作者:JAVA·D·WangJing  
本文主要介绍了SpringBoot整合Netty实现WebSocket的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、pom.xml依赖配置

<!-- netty -->
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.50.Final</version>
</dependency>

二、代码

2.1、NettyServer 类

package com.wangjing.socket.server;
 
import com.wangjing.socket.handler.CoordinationSocketHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
 
public class CoordinationNettyServer {
 
    private final int port;
 
    public CoordinationNettyServer(int port) {
        this.port = port;
    }
 
 
    public void start() throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            ServerBootstrap sb = new ServerBootstrap();
            sb.option(ChannelOption.SO_BACKLOG, 1024);
            sb.group(group, bossGroup) // 绑定线程池
                    .channel(NioServerSocketChannel.class) // 指定使用的channel
                    .localAddress(this.port)// 绑定监听端口
                    .childHandler(new ChannelInitializer<SocketChannel>() { // 绑定客户端连接时候触发操作
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            //websocket协议本身是基于http协议的,所以这边也要使用http解编码器
                            ch.pipeline().addLast(new HttpServerCodec());
                            //以块的方式来写的处理器
                            ch.pipeline().addLast(new ChunkedWriteHandler());
                            ch.pipeline().addLast(new HttpObjectAggregator(8192));
                            ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10));
                            ch.pipeline().addLast(new CoordinationSocketHandler());//自定义消息处理类
                        }
                    });
            ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定
            System.out.println(CoordinationNettyServer.class + "已启动,正在监听: " + cf.channel().localAddress());
            cf.channel().closeFuture().sync(); // 关闭服务器通道
        } finally {
            group.shutdownGracefully().sync(); // 释放线程池资源
            bossGroup.shutdownGracefully().sync();
        }
    }
}
 

2.2、SocketHandler 类

package com.wangjing.socket.handler;
 
import com.wangjing.socket.pool.CoordinationChannelHandlerPool;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
 
public class CoordinationSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
 
 
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("与客户端建立连接,通道开启!");
        //添加到channelGroup通道组
        CoordinationChannelHandlerPool.channelGroup.add(ctx.channel());
    }
 
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("与客户端断开连接,通道关闭!");
        //从channelGroup通道组删除
        CoordinationChannelHandlerPool.channelGroup.remove(ctx.channel());
    }
 
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        //接收的消息
        System.out.println(String.format("收到客户端%s的数据:%s", ctx.channel().id(), msg.text()));
 
        // 单独发消息
        // sendMessage(ctx);
        // 群发消息
        sendAllMessage();
    }
 
    private void sendMessage(ChannelHandlerContext ctx) throws InterruptedException {
        String message = "我是服务器,你好呀";
        ctx.writeAndFlush(new TextWebSocketFrame("hello"));
    }
 
    private void sendAllMessage() {
        String message = "我是服务器,这是群发消息";
        CoordinationChannelHandlerPool.channelGroup.writeAndFlush(new TextWebSocketFrame(message));
    }
 
 
}

2.3、ChannelHandlerPool 类

package com.wangjing.socket.pool;
 
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
 
public class CoordinationChannelHandlerPool {
 
    public CoordinationChannelHandlerPool() {
    }
 
    //可以存储userId与ChannelId的映射表
//    public static ConcurrentHashMap<String, ChannelId> channelIdMap = new ConcurrentHashMap<>();
 
    //channelGroup通道组
    public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
 
}

2.4、Application启动类

package com.wangjing.socket;
 
import com.wangjing.socket.server.CoordinationNettyServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication(scanBasePackages = "com.wangjing")
public class SocketApplication {
 
 
    public static void main(String[] args) {
        SpringApplication.run(SocketApplication.class, args);
 
        try {
            new CoordinationNettyServer(8804).start();
        } catch (Exception e) {
            System.out.println("NettyServerError:" + e.getMessage());
        }
    }
 
}

三、测试

websocket 在线测试推荐:在线websocket测试-online tool-postjson

到此这篇关于SpringBoot整合Netty实现WebSocket的示例代码的文章就介绍到这了,更多相关SpringBoot整合Netty实现WebSocket内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • Java Mybatis查询数据库举例详解

    Java Mybatis查询数据库举例详解

    这篇文章主要给大家介绍了关于Java Mybatis查询数据库的相关资料,在MyBatis中可以使用递归查询实现对数据库中树形结构数据的查询,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-10-10
  • Java任务调度的常见实现方法与比较详解

    Java任务调度的常见实现方法与比较详解

    这篇文章主要介绍了Java任务调度的常见实现方法与比较,结合实例形式分析了Java任务调度的四种常见实现方法,使用区别及相关注意事项,需要的朋友可以参考下
    2017-08-08
  • Javacsv实现Java读写csv文件

    Javacsv实现Java读写csv文件

    这篇文章主要为大家详细介绍了Javacsv实现Java读写csv文件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-07-07
  • Java对int[]数组做新增删除去重操作代码

    Java对int[]数组做新增删除去重操作代码

    这篇文章主要介绍了Java里面对int[]数组做新增删除去重实现,这里记录下使用int[]数组对数组进行新增删除去重等操作,用来更加了解java里面的集合类思想,需要的朋友可以参考下
    2023-10-10
  • JavaWeb三大组件之监听器Listener详解

    JavaWeb三大组件之监听器Listener详解

    这篇文章主要介绍了JavaWeb三大组件之监听器Listener详解,在JavaWeb应用程序中,Listener监听器是一种机制,用于监听和响应特定的事件,它可以感知并响应与应用程序相关的事件,从而执行相应的逻辑处理,需要的朋友可以参考下
    2023-10-10
  • JAVA不使用线程池来处理的异步的方法详解

    JAVA不使用线程池来处理的异步的方法详解

    这篇文章主要介绍了JAVA不使用线程池来处理的异步的方法,在这个示例中,asyncTask方法创建了一个新的线程来执行异步任务,这个新线程会立即开始执行,而主线程则会继续执行后续的代码,感兴趣的朋友跟随小编一起看看吧
    2024-05-05
  • Java父线程(或是主线程)等待所有子线程退出的实例

    Java父线程(或是主线程)等待所有子线程退出的实例

    下面小编就为大家分享一篇Java父线程(或是主线程)等待所有子线程退出的实例,具有很好的参考价值,希望对大家有所帮助
    2017-11-11
  • java中的空指针异常情况以及解决方案

    java中的空指针异常情况以及解决方案

    这篇文章主要介绍了java中的空指针异常情况以及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • 线程池中使用spring aop事务增强

    线程池中使用spring aop事务增强

    这篇文章主要介绍了线程池中使用spring aop事务增强,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Java 8 Stream流强大的原理

    Java 8 Stream流强大的原理

    这篇文章主要介绍了Java 8 Stream流强大的原理,Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。本文会对Stream的实现原理进行剖析,具有一定的参考价值,需要的朋友可以参考一下
    2021-12-12

最新评论