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