SpringBoot+Netty 防止主线程阻塞

 

https://blog.csdn.net/qq_31145141/article/details/103864600

 

@SpringBootApplication
@MapperScan("com.lhb.dao") // mybatis扫描
@EnableAsync//注意这里,这个注解启用了线程池
public class Application extends SpringApplication {
    public static void main(String[] args) {
        SpringApplication.run(Application.class);
        System.out.println("SpringBoot start");
    }
}

  

 

 

package com.lhb.netty;
 
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
 
import javax.annotation.PreDestroy;
 
/**
 * 作者:Haibo.Liu
 * 描述:
 * 日期: 2019/4/23
 * QQ:836915746
 */
@Component//当成组件处理
@Order(value = 1)//这里表示启动顺序
public class Server implements CommandLineRunner {
 
    private Logger logger = LoggerFactory.getLogger(this.getClass());
 
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private Channel channel;
 
    public void start() {
        bossGroup = new NioEventLoopGroup(); //监听线程组,监听客户请求
        workerGroup = new NioEventLoopGroup();//处理客户端相关操作线程组,负责处理与客户端的数据通讯
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            //设置监听组,线程组,初始化器
            serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer() {
                @Override
                protected void initChannel(Channel channel) {
                    ChannelPipeline pipeline = channel.pipeline();
                    pipeline.addLast(new ServerHandler());
                    logger.info("Client :" + channel.remoteAddress() + "已经连接上");
                }
            });
            logger.info("Netty Server start");
            //绑定端口号
            ChannelFuture f = serverBootstrap.bind(6300).sync();
            channel = f.channel().closeFuture().sync().channel();//这里绑定端口启动后,会阻塞线程,也就是为什么要用线程池启动的原因
 
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
            stop();
            logger.info("Netty Server close");
        }
    }
 
    @PreDestroy
    public void stop() {
        if (channel != null) {
            logger.info("Netty Server close");
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
 
    @Async//注意这里,组件启动时会执行run,这个注解是让线程异步执行,这样不影响主线程
    @Override
    public void run(String... args) {
        start();
    }
}

  

package com.lhb.netty;
 
import com.lhb.dao.WtsrEquipmentMapper;
import com.lhb.redis.RedisUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
 
import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
/**
 * 作者:Haibo.Liu
 * 描述:
 * 日期: 2019/4/23
 * QQ:836915746
 */
@Component//ServerHandler 当成组件处理,这样可以直接注入bean
public class ServerHandler extends ByteToMessageDecoder {
 
    private static Logger logger = LoggerFactory.getLogger(ServerHandler.class);
 
    //这里是你要注入的bean
    private static RedisUtil redisUtil;
    private static WtsrEquipmentMapper wtsrEquipmentMapper;
 
    @Resource
    public void setWtsrEquipmentMapper(WtsrEquipmentMapper wtsrEquipmentMapper) {
        ServerHandler.wtsrEquipmentMapper = wtsrEquipmentMapper;
    }
 
    @Resource
    public void setRedisUtil(RedisUtil redisUtil) {
        ServerHandler.redisUtil = redisUtil;
    }
 
 
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        byte[] bytes = new byte[in.readableBytes()];
        in.readBytes(bytes);
        
    }
 
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        Channel incoming = ctx.channel();
        cause.printStackTrace();
        ctx.close();
    }
 
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        logger.info("tcp断开");
        ctx.fireChannelInactive();
        Channel channel = ctx.channel();
        if (channel != null && channel.isActive()) {
            ctx.close();
        }
    }
 
  
 
    public static void sendDeviceMsg(ChannelHandlerContext ctx, String msg) {
        if (ctx != null) {
            byte[] bytes = msg.getBytes();
            ByteBuf encoded = ctx.alloc().buffer(bytes.length);
            encoded.writeBytes(bytes);
            ctx.channel().writeAndFlush(encoded);
        }
    }
 
 
}

  

posted @ 2020-09-25 09:49  2eggs  Views(1483)  Comments(0Edit  收藏  举报