• springboot集成netty实现websocket


    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-websocket</artifactId>
            </dependency>
            <dependency>
                <groupId>io.netty</groupId>
                <artifactId>netty-all</artifactId>
                <version>4.1.50.Final</version>
            </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    @SpringBootApplication
    public class RouteDefenseApplication implements CommandLineRunner {
    
        public static void main(String[] args) {
            SpringApplication.run(RouteDefenseApplication.class, args);
            System.out.println("启动成功!");
        }
    
        @Autowired
        private NettyServer nettyServer;
    
        @Override
        public void run(String... args) throws Exception {
            new Thread(nettyServer).start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    @Component
    public class NettyServer implements Runnable{
    
        public void start(InetSocketAddress address) {
         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(address)// 绑定监听端口
                        .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 MyWebSocketHandler());//自定义消息处理类
                            }
                        });
                        ChannelFuture cf = sb.bind(address).sync(); // 服务器异步创建绑定
                System.out.println(NettyServer.class + "已启动,正在监听: " + cf.channel().localAddress());
                cf.channel().closeFuture().sync(); // 关闭服务器通道
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
            try {
                    group.shutdownGracefully().sync(); // 释放线程池资源
                    bossGroup.shutdownGracefully().sync();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                }
        }
    
        @Override
        public void run() {
            InetSocketAddress address = new InetSocketAddress(10007);
            this.start(address);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    public class MyWebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    
        private static final Logger logger = LoggerFactory.getLogger(MyWebSocketHandler.class);
    
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            System.out.println("与客户端建立连接,通道开启!");
            //添加到channelGroup通道组
            MyChannelHandlerPool.channelGroup.add(ctx.channel());
        }
        
        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            System.out.println("与客户端断开连接,通道关闭!");
            //从channelGroup通道组删除
            MyChannelHandlerPool.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){
            String message = "消息";
            ctx.writeAndFlush(new TextWebSocketFrame(message));
        }
    
        private void sendAllMessage(){
            String message = "我是服务器,这是群发消息";
            MyChannelHandlerPool.channelGroup.writeAndFlush(new TextWebSocketFrame(message));
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    public class MyChannelHandlerPool {
        public MyChannelHandlerPool() {
        }
    
        //可以存储userId与ChannelId的映射表
        public static ConcurrentHashMap<String, ChannelId> channelIdMap = new ConcurrentHashMap<>();
    
        //channelGroup通道组
        public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    发送消息:

    MyChannelHandlerPool.channelGroup.writeAndFlush("我是后端消息!!!!!");
    
    • 1
  • 相关阅读:
    【Qt控件之QToolBox】介绍及使用
    汽车辅助系统
    JavaSE 第七章 面向对象基础(下)静态&枚举&抽象类
    LeetCode 每日一题 2022/8/15-2022/8/21
    使用create-react-app创建react应用
    Redis-核心数据结构
    暑假加餐|有钱人和你想的不一样(第8天)+多目标金鹰优化算法(Matlab代码实现)
    陪诊系统|陪诊软件革新陪诊体验解决病患难题
    深度学习YOLO抽烟行为检测 - python opencv 计算机竞赛
    LeetCode【128】最长连续序列
  • 原文地址:https://blog.csdn.net/zk_1325572803/article/details/134006824