|
@@ -1,133 +0,0 @@
|
|
|
-package com.caimei365.user.components;
|
|
|
-
|
|
|
-import com.caimei365.user.model.ResponseJson;
|
|
|
-import com.caimei365.user.service.LoginService;
|
|
|
-import io.netty.bootstrap.ServerBootstrap;
|
|
|
-import io.netty.channel.*;
|
|
|
-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.TextWebSocketFrame;
|
|
|
-import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
|
|
|
-import io.netty.handler.logging.LogLevel;
|
|
|
-import io.netty.handler.logging.LoggingHandler;
|
|
|
-import io.netty.handler.stream.ChunkedWriteHandler;
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.boot.ApplicationArguments;
|
|
|
-import org.springframework.boot.ApplicationRunner;
|
|
|
-import org.springframework.core.annotation.Order;
|
|
|
-import org.springframework.stereotype.Component;
|
|
|
-
|
|
|
-/**
|
|
|
- * @author Aslee
|
|
|
- * @date 2021/3/10
|
|
|
- */
|
|
|
-@Slf4j
|
|
|
-@Order(value = 100000000)
|
|
|
-@Component
|
|
|
-public class NettyServer implements ApplicationRunner {
|
|
|
- private LoginService loginService;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- public void setLoginService(LoginService loginService) throws Exception {
|
|
|
- this.loginService = loginService;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void run(ApplicationArguments args) throws Exception {
|
|
|
- // 创建2个线程组
|
|
|
- EventLoopGroup boss=new NioEventLoopGroup(1);
|
|
|
- // NettyRuntime.availableProcessors() * 2) 默认创建的线程个数
|
|
|
- EventLoopGroup work=new NioEventLoopGroup();
|
|
|
- ServerBootstrap serverBootstrap = new ServerBootstrap();
|
|
|
- try {
|
|
|
- serverBootstrap.group(boss, work);
|
|
|
- serverBootstrap.channel(NioServerSocketChannel.class);
|
|
|
- // Netty提供的日志handler
|
|
|
- serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));
|
|
|
- serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
|
|
|
- @Override
|
|
|
- protected void initChannel(SocketChannel ch) throws Exception {
|
|
|
- ChannelPipeline pipeline = ch.pipeline();
|
|
|
- //基于http协议,使用http的编码和解码器
|
|
|
- pipeline.addLast(new HttpServerCodec());
|
|
|
- //以块方式写,添加ChunkedWriteHandler处理器
|
|
|
- pipeline.addLast(new ChunkedWriteHandler());
|
|
|
- /*
|
|
|
- 1. http数据在传输过程中是分段, HttpObjectAggregator ,就是可以将多个段聚合
|
|
|
- 2. 这就就是为什么,当浏览器发送大量数据时,就会发出多次http请求
|
|
|
- */
|
|
|
- pipeline.addLast(new HttpObjectAggregator(7168));
|
|
|
- /*
|
|
|
- 1. 对应websocket ,它的数据是以 帧(frame) 形式传递
|
|
|
- 2. 可以看到WebSocketFrame 下面有六个子类
|
|
|
- 3. 浏览器请求时 ws://localhost:9000/demo 表示请求的uri
|
|
|
- 4. WebSocketServerProtocolHandler 核心功能是将 http协议升级为 ws协议 , 保持长连接
|
|
|
- 5. 是通过一个 状态码 101
|
|
|
- */
|
|
|
- pipeline.addLast(new WebSocketServerProtocolHandler("/demo"));
|
|
|
-
|
|
|
- //自定义的handler ,处理业务逻辑
|
|
|
- pipeline.addLast(new MyTextWebSocketFrameHandler());
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- //启动服务器
|
|
|
- ChannelFuture channelFuture = serverBootstrap.bind(9000).sync();
|
|
|
- channelFuture.channel().closeFuture().sync();
|
|
|
- }finally {
|
|
|
- boss.shutdownGracefully();
|
|
|
- work.shutdownGracefully();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- public class MyTextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
|
|
|
- @Override
|
|
|
- protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
|
|
|
- log.info("收到登录请求,开始验证state:" + msg.text());
|
|
|
- // 收到登录请求,根据安全认证state调用登录验证方法
|
|
|
- ResponseJson responseJson = loginService.qrCodeAuthScanResult(msg.text());
|
|
|
- Integer count = 0;
|
|
|
- // 若验证返回码不为0且验证次数小于60次,重新调用验证
|
|
|
- while (responseJson.getCode() != 0 && count<60) {
|
|
|
- count++;
|
|
|
- // 返回验证结果
|
|
|
- ctx.channel().writeAndFlush(new TextWebSocketFrame("验证结果:" + responseJson.getCode() + "-" + responseJson.getMsg()));
|
|
|
- Thread.sleep(1000);
|
|
|
- // 重新调用登录验证方法
|
|
|
- responseJson = loginService.qrCodeAuthScanResult(msg.text());
|
|
|
- }
|
|
|
- ctx.channel().writeAndFlush(new TextWebSocketFrame("验证结果:" + responseJson.getCode() + "-" + responseJson.getMsg()));
|
|
|
- // 关闭连接
|
|
|
- ctx.close();
|
|
|
- }
|
|
|
-
|
|
|
- // 当web客户端连接后,触发方法
|
|
|
- @Override
|
|
|
- public void handlerAdded(ChannelHandlerContext ctx){
|
|
|
- //id 表示唯一的值,LongText 是唯一的 ShortText 不是唯一
|
|
|
-// System.out.println("handlerAdded 被调用 id" + ctx.channel().id());
|
|
|
-// System.out.println("handlerAdded 被调用" + ctx.channel().id().asLongText());
|
|
|
-// System.out.println("handlerAdded 被调用" + ctx.channel().id().asShortText());
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- @Override
|
|
|
- public void handlerRemoved(ChannelHandlerContext ctx){
|
|
|
- log.info("连接关闭");
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause){
|
|
|
- // 抛出异常
|
|
|
- cause.printStackTrace();
|
|
|
- // 关闭连接
|
|
|
- ctx.close();
|
|
|
- }
|
|
|
- }
|
|
|
-}
|