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);
        }
    }
 
 
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM