##### 一、SpringBoot2+Netty+WebSocket(netty实现websocket,支持URL参数)
原文链接: https://zhengkai.blog.csdn.net/article/details/91552993
思路: 用netty实现 后台的 websocket 相当于前端利用websocket协议 后端用netty实现复杂的业务逻辑
io.netty
netty-all
4.1.36.Final
SpringBootApplication
启动器中需要new一个NettyServer,并显式调用启动netty。
@SpringBootApplication
public class SpringCloudStudyDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudStudyDemoApplication.class,args);
try {
new NettyServer(12345).start();
System.out.println("https://blog.csdn.net/moshowgame");
System.out.println("http://127.0.0.1:6688/netty-websocket/index");
}catch(Exception e) {
System.out.println("NettyServerError:"+e.getMessage());
}
}
}
其中 ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", null, true, 65536 * 10)); 请求为 websocket
/**
* NettyServer Netty服务器配置
* @author zhengkai.blog.csdn.net
* @date 2019-06-12
*/
public class NettyServer {
private final int port;
public NettyServer(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() { // 绑定客户端连接时候触发操作
@Override
protected void initChannel(SocketChannel ch) throws Exception {
System.out.println("收到新连接");
//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", null, true, 65536 * 10));
ch.pipeline().addLast(new MyWebSocketHandler());
}
});
ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定
System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress());
cf.channel().closeFuture().sync(); // 关闭服务器通道
} finally {
group.shutdownGracefully().sync(); // 释放线程池资源
bossGroup.shutdownGracefully().sync();
}
}
}
MyChannelHandlerPool
通道组池,管理所有websocket连接
/**
* MyChannelHandlerPool
* 通道组池,管理所有websocket连接
* @author zhengkai.blog.csdn.net
* @date 2019-06-12
*/
public class MyChannelHandlerPool {
public MyChannelHandlerPool(){}
public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
}
MyWebSocketHandler
处理ws一下几种情况:
channelActive与客户端建立连接
channelInactive与客户端断开连接
channelRead0客户端发送消息处理
/**
* NettyServer Netty服务器配置
* @author zhengkai.blog.csdn.net
* @date 2019-06-12
*/
public class NettyServer {
private final int port;
public NettyServer(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() { // 绑定客户端连接时候触发操作
@Override
protected void initChannel(SocketChannel ch) throws Exception {
System.out.println("收到新连接");
//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().sync(); // 服务器异步创建绑定
System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress());
cf.channel().closeFuture().sync(); // 关闭服务器通道
} finally {
group.shutdownGracefully().sync(); // 释放线程池资源
bossGroup.shutdownGracefully().sync();
}
}
}
socket.html
主要是连接ws,发送消息,以及消息反馈
Netty-Websocket
Controller
写好了html当然还需要一个controller来引导页面。
@RestController
public class IndexController {
@GetMapping("/index")
public ModelAndView index(){
ModelAndView mav=new ModelAndView("socket");
mav.addObject("uid", RandomUtil.randomNumbers(6));
return mav;
}
}
版权声明:本文为CSDN博主「Moshow郑锴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/moshowgame/article/details/91552993
涉及问题解答**
1、
3个问题: 1.如何主动后台推送,而不是通过前端发送才进行消息推送 2.如果需要部署到域名,不用ip+port访问,使用了netty,端口肯定与项目本身不同时,该如何统一项目和ws的域名地址 3.使用前后端跨域要怎么处理? 小白一枚。希望博主从百忙中抽空回复2 年前回复
西城无故事回复: 1. 用其他的触发条件 (如定时器、线程)触发发送操作。 23. nginx配置反向代理2
2、
问个问题,虽然netty很好,但毕竟springboot原生也支持websocket,而且开发体验更棒,应用中也没发现问题,使用netty是不是多此一举?10 月前回复
留住风的小树回复華灯初上:可以做到方法级别的权限控制,因为调用是wss,最终还是要进到你写的方法的,可以在websocket请求时带上特定的参数7 月前回复
留住风的小树回复華灯初上:可以做到方法级别的权限控制,因为调用是wss,最终还是要尽到你写的方法的,可以在websocket请求时带上特定的参数7 月前回复
码哥码哥華灯初上回复留住风的小树:我有个问题,如果这样集成netty 那不相当于重新开一个端口,就把springmvc就屏蔽了,这样对权限的认证需要自己重写? 我的理解对吗?7 月前回复
留住风的小树回复:性能问题而已
##### 二、SpringBoot2.0集成WebSocket,实现后台向前端推送信息
原文连接:链接: https://blog.csdn.net/moshowgame/article/details/80275084#google_vignette