• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

SpringBoot+Netty+WebSocket 实现消息推送

武飞扬头像
技术琐事
帮助1

Netty 是一个利用 Java 的高级网络的能力,隐藏底层的复杂性而提供一个易于使用/使用其服务器的 API 的客户端框架。

基于 Spring Boot MyBatis Plus Vue & Element 实现的后台管理系统 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

Maven依赖

<dependencies>
&nbsp; <!--&nbsp;https://mvnrepository.com/artifact/io.netty/netty-all&nbsp;-->
&nbsp; <dependency>
&nbsp;&nbsp; <groupId>io.netty </groupId>
&nbsp;&nbsp; <artifactId>netty-all </artifactId>
&nbsp;&nbsp; <version>4.1.36.Final </version>
&nbsp; </dependency>

</dependencies>

基于 Spring Cloud Alibaba Gateway Nacos RocketMQ Vue & Element 实现的后台管理系统 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://gitee.com/zhijiantianya/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

启动器中需要new一个NettyServer,并显式调用netty。

@SpringBootApplication
public&nbsp; class&nbsp;SpringCloudStudyDemoApplication&nbsp;{
&nbsp; public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;SpringApplication.run(SpringCloudStudyDemoApplication .class,args);
&nbsp;&nbsp; try&nbsp;{
&nbsp;&nbsp;&nbsp; new&nbsp;NettyServer( 12345).start();
&nbsp;&nbsp;&nbsp;System.out.println( "https://blog.csdn.net/moshowgame");
&nbsp;&nbsp;&nbsp;System.out.println( "http://127.0.0.1:6688/netty-websocket/index");
&nbsp;&nbsp;} catch(Exception&nbsp;e)&nbsp;{
&nbsp;&nbsp;&nbsp;System.out.println( "NettyServerError:" e.getMessage());
&nbsp;&nbsp;}
&nbsp;}
}

网络服务器

启动的NettyServer,这里进行配置

/**
&nbsp;*&nbsp;NettyServer&nbsp;Netty服务器配置
&nbsp;*&nbsp;@author&nbsp;zhengkai.blog.csdn.net
&nbsp;*&nbsp;@date&nbsp;2019-06-12
&nbsp;*/

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

通道组池,管理所有websocket连接

/**
&nbsp;*&nbsp;MyChannelHandlerPool
&nbsp;*&nbsp;通道组池,管理所有websocket连接
&nbsp;*&nbsp;@author&nbsp;zhengkai.blog.csdn.net
&nbsp;*&nbsp;@date&nbsp;2019-06-12
&nbsp;*/

public&nbsp; class&nbsp;MyChannelHandlerPool&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;MyChannelHandlerPool(){}

&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp; static&nbsp;ChannelGroup&nbsp;channelGroup&nbsp;=&nbsp; new&nbsp;DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

}

MyWebSocketHandler

处理ws一下几种情况:

  • channelActive与客户端建立连接
  • channelInactive与客户端连接破坏
  • channelRead0客户端发送消息处理

/**
&nbsp;*&nbsp;NettyServer&nbsp;Netty服务器配置
&nbsp;*&nbsp;@author&nbsp;zhengkai.blog.csdn.net
&nbsp;*&nbsp;@date&nbsp;2019-06-12
&nbsp;*/

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

主要是连接ws,发送消息,以及消息反馈

<!DOCTYPE&nbsp;html&nbsp;PUBLIC&nbsp;"-//W3C//DTD&nbsp;XHTML&nbsp;1.0&nbsp;Transitional//EN"&nbsp;"http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtd">
<html&nbsp;xmlns="http://www.w3.org/1999/xhtml">
<head>
&nbsp;&nbsp;&nbsp;&nbsp; <meta&nbsp;http-equiv="Content-Type"&nbsp;content="text/html;&nbsp;charset=utf-8"&nbsp;/>
&nbsp;&nbsp;&nbsp;&nbsp; <title>Netty-Websocket </title>
&nbsp;&nbsp;&nbsp;&nbsp; <script&nbsp;type="text/javascript">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;by&nbsp;zhengkai.blog.csdn.net
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;socket;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!window.WebSocket){


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.WebSocket&nbsp;=&nbsp;window.MozWebSocket;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(window.WebSocket){


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket&nbsp;=&nbsp;new&nbsp;WebSocket("ws://127.0.0.1:12345/ws");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.onmessage&nbsp;=&nbsp;function(event){


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;ta&nbsp;=&nbsp;document.getElementById('responseText');
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ta.value&nbsp; =&nbsp;event.data "\r\n";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.onopen&nbsp;=&nbsp;function(event){


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;ta&nbsp;=&nbsp;document.getElementById('responseText');
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ta.value&nbsp;=&nbsp;"Netty-WebSocket服务器。。。。。。连接&nbsp;&nbsp;\r\n";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.onclose&nbsp;=&nbsp;function(event){


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;ta&nbsp;=&nbsp;document.getElementById('responseText');
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ta.value&nbsp;=&nbsp;"Netty-WebSocket服务器。。。。。。关闭&nbsp;\r\n";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}else{


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert("您的浏览器不支持WebSocket协议!");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;send(message){


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!window.WebSocket){

return;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(socket.readyState&nbsp;==&nbsp;WebSocket.OPEN){


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.send(message);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}else{


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert("WebSocket&nbsp;连接没有建立成功!");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; </script>
</head>
<body>
<form&nbsp;onSubmit="return&nbsp;false;">
&nbsp;&nbsp;&nbsp;&nbsp; <label>ID </label> <input&nbsp;type="text"&nbsp;name="uid"&nbsp;value="${uid!!}"&nbsp;/>&nbsp; <br&nbsp;/>
&nbsp;&nbsp;&nbsp;&nbsp; <label>TEXT </label> <input&nbsp;type="text"&nbsp;name="message"&nbsp;value="这里输入消息"&nbsp;/>&nbsp; <br&nbsp;/>
&nbsp;&nbsp;&nbsp;&nbsp; <br&nbsp;/>&nbsp; <input&nbsp;type="button"&nbsp;value="发送ws消息"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onClick="send(this.form.uid.value ':' this.form.message.value)"&nbsp;/>
&nbsp;&nbsp;&nbsp;&nbsp; <hr&nbsp;color="black"&nbsp;/>
&nbsp;&nbsp;&nbsp;&nbsp; <h3>服务端返回的应答消息 </h3>
&nbsp;&nbsp;&nbsp;&nbsp; <textarea&nbsp;id="responseText"&nbsp;style="width:&nbsp;1024px;height:&nbsp;300px;"> </textarea>
</form>
</body>
</html>

控制器

写好当然html还需要一个控制器来引导页面。

@RestController
public&nbsp; class&nbsp;IndexController&nbsp;{
&nbsp;
&nbsp; @GetMapping( "/index")
&nbsp; public&nbsp;ModelAndView&nbsp;&nbsp;index(){
&nbsp;&nbsp;ModelAndView&nbsp;mav= new&nbsp;ModelAndView( "socket");
&nbsp;&nbsp;mav.addObject( "uid",&nbsp;RandomUtil.randomNumbers( 6));
&nbsp;&nbsp; return&nbsp;mav;
&nbsp;}
&nbsp;
}

学新通 学新通

1.首先,调整一下加载处理程序的顺序,优先MyWebSocketHandler在WebSocketServerProtocolHandler上面。

ch.pipeline().addLast( new&nbsp;MyWebSocketHandler());
ch.pipeline().addLast( new&nbsp;WebSocketServerProtocolHandler( "/ws",&nbsp; null,&nbsp; true,&nbsp; 65536&nbsp;*&nbsp; 10));

2.之后,会通过某种方式,会通过某种方式,获取一个完整的URL地址,是一个接受信息的MyWebSocketHandler话。channelRead``FullHttpRequest``FullHttpRequest.uri()``TextWebSocketFrame

public&nbsp; class&nbsp;MyWebSocketHandler&nbsp;extends&nbsp;SimpleChannelInboundHandler<TextWebSocketFrame>&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp; @Override
&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;void&nbsp;channelActive(ChannelHandlerContext&nbsp;ctx)&nbsp;throws&nbsp;Exception&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "与客户端建立连接,通道开启!");

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //添加到channelGroup通道组
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyChannelHandlerPool.channelGroup.add(ctx.channel());
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp; @Override
&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;void&nbsp;channelInactive(ChannelHandlerContext&nbsp;ctx)&nbsp;throws&nbsp;Exception&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "与客户端断开连接,通道关闭!");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //添加到channelGroup&nbsp;通道组
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyChannelHandlerPool.channelGroup.remove(ctx.channel());
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp; @Override
&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;void&nbsp;channelRead(ChannelHandlerContext&nbsp;ctx,&nbsp;Object&nbsp;msg)&nbsp;throws&nbsp;Exception&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //首次连接是FullHttpRequest,处理参数&nbsp;by&nbsp;zhengkai.blog.csdn.net
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp;( null&nbsp;!=&nbsp;msg&nbsp;&&&nbsp;msg&nbsp; instanceof&nbsp;FullHttpRequest)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FullHttpRequest&nbsp;request&nbsp;=&nbsp;(FullHttpRequest)&nbsp;msg;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;uri&nbsp;=&nbsp;request.uri();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map&nbsp;paramMap=getUrlParams(uri);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "接收到的参数是:" JSON.toJSONString(paramMap));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //如果url包含参数,需要处理
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(uri.contains( "?")){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;newUri=uri.substring( 0,uri.indexOf( "?"));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(newUri);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;request.setUri(newUri);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} else&nbsp; if(msg&nbsp; instanceof&nbsp;TextWebSocketFrame){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //正常的TEXT消息类型
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TextWebSocketFrame&nbsp;frame=(TextWebSocketFrame)msg;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "客户端收到服务器数据:"&nbsp; frame.text());
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sendAllMessage(frame.text());
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.channelRead(ctx,&nbsp;msg);
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp; @Override
&nbsp;&nbsp;&nbsp;&nbsp; protected&nbsp;void&nbsp;channelRead0(ChannelHandlerContext&nbsp;channelHandlerContext,&nbsp;TextWebSocketFrame&nbsp;textWebSocketFrame)&nbsp;throws&nbsp;Exception&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp; private&nbsp;void&nbsp;sendAllMessage(String&nbsp;message){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //收到信息后,群发给所有channel
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyChannelHandlerPool.channelGroup.writeAndFlush(&nbsp; new&nbsp;TextWebSocketFrame(message));
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp; private&nbsp;static&nbsp;Map&nbsp;getUrlParams(String&nbsp;url){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map<String,String>&nbsp;map&nbsp;=&nbsp; new&nbsp;HashMap<>();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url&nbsp;=&nbsp;url.replace( "?", ";");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp;(!url.contains( ";")){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;map;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp;(url.split( ";").length&nbsp;>&nbsp; 0){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[]&nbsp;arr&nbsp;=&nbsp;url.split( ";")[ 1].split( "&");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for&nbsp;(String&nbsp;s&nbsp;:&nbsp;arr){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;key&nbsp;=&nbsp;s.split( "=")[ 0];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;value&nbsp;=&nbsp;s.split( "=")[ 1];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.put(key,value);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp;map;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} else{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;map;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}

3.html中的ws地址也进行了改造

socket&nbsp;=&nbsp; new&nbsp;WebSocket( "ws://127.0.0.1:12345/ws?uid=666&gid=777");

  1. 改造后输出情况

收到新连接
与客户端建立连接,通道开启!
接收到的参数是:{ "uid": "666", "gid": "777"}
/ws
客户端收到服务器数据: 142531:这里输入消息
客户端收到服务器数据: 142531:这里输入消息
客户端收到服务器数据: 142531:这里输入消息

失败:WebSocket 打开握手超时

听说是 ssl wss 的情况下会出现,来自@around-gao 的解决方法:

把MyWebSocketHandler和WebSocketServerProtocolHandler调下顺序就好了。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgbkkhb
系列文章
更多 icon
同类精品
更多 icon
继续加载