maven 引入包:
<!-- websocket -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.36.Final</version>
</dependency>
netty 启动server类:
package com.minivision.user.manage.websocket;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import io.netty.bootstrap.ServerBootstrap;
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.codec.serialization.ObjectEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;
/**
* webSocket启动server <br>
*
* @author yangxiaodong<br>
* @version 1.0<br>
* @taskId <br>
* @CreateDate 2019年7月22日 <br>
*/
@Component
public class NettyServer {
/**
* 调测日志
*/
private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketHandler.class);
/**
* websocket协议名 <br>
*/
private static final String WEBSOCKET_PROTOCOL = "WebSocket";
/**
* 端口号 <br>
*/
@Value("${websocket.netty.port:58080}")
private int port;
/**
* wesocket路径 <br>
*/
@Value("${websocket.netty.path:/websocket}")
private String websocketPath;
/**
* websokcet处理器 <br>
*/
@Autowired
private WebSocketHandler webSocketHandler;
/**
* permissionWebSocketHandler <br>
*/
@Autowired
private PermissionWebSocketHandler permissionWebSocketHandler;
/**
* bossGroup <br>
*/
private EventLoopGroup bossGroup;
/**
* parentGroup <br>
*/
private EventLoopGroup group;
/**
* 启动: <br>
*
* @author yangxiaodong<br>
* @throws InterruptedException
* @taskId <br>
* @throws InterruptedException <br>
*/
@PostConstruct
public void start() throws InterruptedException {
bossGroup = new NioEventLoopGroup();
group = new NioEventLoopGroup();
ServerBootstrap sb = new ServerBootstrap();
sb.option(ChannelOption.SO_BACKLOG, 1024);// 配置TCP参数,握手字符串长度设置
sb.group(group, bossGroup) // group辅助客户端的tcp连接请求 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 ObjectEncoder());
// 以块的方式来写的处理器
ch.pipeline().addLast(new ChunkedWriteHandler());
ch.pipeline().addLast(new HttpObjectAggregator(8192));
ch.pipeline().addLast(permissionWebSocketHandler);
ch.pipeline().addLast(new WebSocketServerProtocolHandler(websocketPath, WEBSOCKET_PROTOCOL, true, 65536 * 10));
ch.pipeline().addLast(webSocketHandler);
}
});
// 服务器异步创建绑定
sb.bind().sync();
LOGGER.info("websocket server start");
}
/**
* 释放线程池资源: <br>
*
* @author yangxiaodong<br>
* @taskId <br>
* @throws InterruptedException <br>
*/
@PreDestroy
private void destory() throws InterruptedException {
if (null != bossGroup) {
bossGroup.shutdownGracefully().sync();
}
if (null != group) {
group.shutdownGracefully().sync();
}
}
}
用户登陆验证码处理器:
通过ws后面携带的参数,进行用户登陆校验,
思路:获取到ws参数后,处理连接地址,把携带的参数去掉,否则,channel会自动断开的
package com.minivision.user.manage.websocket;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.minivision.user.manage.util.UrlUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
/**
* websocket 用户登陆验证码处理器 <br>
*
* @author yangxiaodong<br>
* @version 1.0<br>
* @taskId <br>
* @CreateDate 2019年8月1日 <br>
*/
@Component
@Sharable
public class PermissionWebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
/**
* 调测日志
*/
private static final Logger LOGGER = LoggerFactory.getLogger(PermissionWebSocketHandler.class);
/**
* wesocket路径 <br>
*/
@Value("${websocket.netty.path:/websocket}")
private String websocketPath;
/**
* 重新方法,获取url中参数,进行权限验证: <br>
*