netty
关于最近我所学的netty内容,在语雀上
https://www.yuque.com/u492757/psgrno/yl91yg
Netty tcp在netty中的使用
MyServer
package com.zhetang.netty; import com.zhetang.mapper.mysqlMapper.BaseUserMapper; 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.string.StringEncoder; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.nio.charset.Charset; import java.util.concurrent.TimeUnit; /** * Created with IntelliJ IDEA. * User:wq * Date:2021/4/19 * Time: 20:12 * Description: No Description */ @Slf4j @Component public class MyServer { // @Value("${my.server.port}") // private static Integer port; @Resource private BaseUserMapper userMapper; private static final Integer portt =8082; public static void init(){ //创建两个线程组 boosGroup、workerGroup EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { //创建服务端的启动对象,设置参数 ServerBootstrap bootstrap = new ServerBootstrap(); //设置两个线程组boosGroup和workerGroup bootstrap.group(bossGroup, workerGroup) //设置服务端通道实现类型 .channel(NioServerSocketChannel.class) //设置线程队列得到连接个数 .option(ChannelOption.SO_BACKLOG, 128) //设置保持活动连接状态 .childOption(ChannelOption.SO_KEEPALIVE, true) //使用匿名内部类的形式初始化通道对象 .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { //给pipeline管道设置处理器 socketChannel.pipeline().addFirst(new MyServerValidateHandler()); socketChannel.pipeline().addLast(new MyServerHandler()); } });//给workerGroup的EventLoop对应的管道设置处理器 log.info("实时数据采集服务端准备就绪!!!!!!"); //绑定端口号,启动服务端 ChannelFuture channelFuture = null; try { channelFuture = bootstrap.bind(portt).sync(); } catch (InterruptedException e) { e.printStackTrace(); } //对关闭通道进行监听 try { channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { //创建两个线程组 boosGroup、workerGroup EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { //创建服务端的启动对象,设置参数 ServerBootstrap bootstrap = new ServerBootstrap(); //设置两个线程组boosGroup和workerGroup bootstrap.group(bossGroup, workerGroup) //设置服务端通道实现类型 .channel(NioServerSocketChannel.class) //设置线程队列得到连接个数 .option(ChannelOption.SO_BACKLOG, 128) //设置保持活动连接状态 .childOption(ChannelOption.SO_KEEPALIVE, true) //使用匿名内部类的形式初始化通道对象 .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { //给pipeline管道设置处理器 socketChannel.pipeline().addFirst(new MyServerValidateHandler()); socketChannel.pipeline().addLast(new MyServerHandler()); } });//给workerGroup的EventLoop对应的管道设置处理器 log.info("实时数据采集服务端准备就绪!!!!!!"); //绑定端口号,启动服务端 ChannelFuture channelFuture = bootstrap.bind(portt).sync(); //对关闭通道进行监听 channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
MyServerHandler
package com.zhetang.netty; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.zhetang.config.QueueConfig; import com.zhetang.mapper.mysqlMapper.BaseUserMapper; import com.zhetang.model.bo.realtime.*; import com.zhetang.model.mysql.lvms.BaseUser; import com.zhetang.model.pojo.DataResult; import com.zhetang.model.pojo.ErrorResult; import com.zhetang.rabbitmq.RabbitMqSender; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.CharsetUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; import javax.annotation.PostConstruct; import java.nio.charset.Charset; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPrivateKey; import java.security.spec.InvalidKeySpecException; import java.util.List; /** * Created with IntelliJ IDEA. * User:wq * Date:2021/4/19 * Time: 20:13 * Description: No Description */ /** * 自定义的Handler需要继承Netty规定好的HandlerAdapter * 才能被Netty框架所关联,有点类似SpringMVC的适配器模式 **/ @Component @Slf4j public class MyServerHandler extends ChannelInboundHandlerAdapter { @Autowired private BaseUserMapper userMapper; private static MyServerHandler myServerHandler; @Autowired private RabbitMqSender rabbitMqSender; @Autowired private QueueConfig queueConfig; @PostConstruct public void init() { myServerHandler = this; myServerHandler.userMapper = this.userMapper; myServerHandler.rabbitMqSender =this.rabbitMqSender; myServerHandler.queueConfig = this.queueConfig; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { BaseUserMapper userMapper = myServerHandler.userMapper; RabbitMqSender rabbitMqSender = myServerHandler.rabbitMqSender; //获取客户端发送过来的消息 FirmCheckDataBO data = null; FirmCheckDataBO checkData = null; String returnClientJson = null; String decodeData = null; ByteBuf byteBuf = (ByteBuf) msg; try { String json = byteBuf.toString(CharsetUtil.UTF_8); FirmCheckDataBO checkDataBO = JSONObject.parseObject(json, FirmCheckDataBO.class); checkData = verifyCheckData(checkDataBO); decodeData = getDecodeData(checkDataBO, userMapper); log.info("解密后:"+decodeData); }catch (RuntimeException e){ e.printStackTrace(); DataResult dataResult = new DataResult(false, checkData.getDataId(), new ErrorResult("未授权的访问")); // ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), CharsetUtil.UTF_8)); ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), Charset.forName("GBK"))); throw new RuntimeException("认证token有误!!!!!!"); } try{ //验证企业数据是否已填 returnClientJson = sendQueueByType(checkData, decodeData,rabbitMqSender); DataResult dataResult = new DataResult(true, checkData.getDataId()); // ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), CharsetUtil.UTF_8)); ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), Charset.forName("GBK"))); }catch (RuntimeException e) { e.printStackTrace(); if (e.getCause() != null) { log.error(e.getCause().getCause().toString()); DataResult dataResult = new DataResult(false, checkData.getDataId(),new ErrorResult(e.getCause().getCause().toString())); // ctx.writeAndFlush(Unpooled.copiedBuffer( JSON.toJSONString(dataResult), CharsetUtil.UTF_8)); ctx.writeAndFlush(Unpooled.copiedBuffer( JSON.toJSONString(dataResult), Charset.forName("GBK"))); throw new RuntimeException("字段未填!!!!!!"); }else { DataResult dataResult = new DataResult(false, checkData.getDataId(),new ErrorResult(e.toString())); ctx.writeAndFlush(Unpooled.copiedBuffer( JSON.toJSONString(dataResult), Charset.forName("GBK"))); throw new RuntimeException("dataType传值有误!!!!!!"); } } } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { //发送消息给客户端 // ctx.writeAndFlush(Unpooled.copiedBuffer("@@", CharsetUtil.UTF_8)); ctx.writeAndFlush(Unpooled.copiedBuffer("@@", Charset.forName("GBK"))); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { //发生异常,关闭通道 log.error("ctx检测到"+ctx.channel().remoteAddress()+"异常!!!!!!",cause); ctx.close(); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { log.error("ctx检测到"+ctx.channel().remoteAddress()+"已断线!!!!!!"); super.channelInactive(ctx); } FirmCheckDataBO verifyCheckData(@Validated FirmCheckDataBO firmCheckDataBO){ FirmCheckDataBO checkDataBO = new FirmCheckDataBO(); BeanUtils.copyProperties(firmCheckDataBO,checkDataBO); return checkDataBO; } /** * 校验 安全监测点位、工艺监测DCS监测点位实时数据 * @param dcsDetectRealTimeBO * @return */ DcsDetectRealTimeBO verifyDcsDetectRealTimeData(@Validated DcsDetectRealTimeBO dcsDetectRealTimeBO){ DcsDetectRealTimeBO detectRealTimeBO = new DcsDetectRealTimeBO(); BeanUtils.copyProperties(dcsDetectRealTimeBO,detectRealTimeBO); return detectRealTimeBO; } /** * 校验 安全监测点位、生产⼯艺(治污工艺)DCS监测点位报警数据 * @param dcsDetectAlarmDataBO * @return */ DcsDetectAlarmDataBO verifyDcsDetectAlarmData(@Validated DcsDetectAlarmDataBO dcsDetectAlarmDataBO){ DcsDetectAlarmDataBO detectAlarmDataBO = new DcsDetectAlarmDataBO(); BeanUtils.copyProperties(dcsDetectAlarmDataBO,detectAlarmDataBO); return detectAlarmDataBO; } /** * 校验 消防点位报警数据 * @param firePointAlarmPointBO * @return */ FirePointAlarmPointBO verifyFirePoint(@Validated FirePointAlarmPointBO firePointAlarmPointBO){ FirePointAlarmPointBO firePointAlarmPoint = new FirePointAlarmPointBO(); BeanUtils.copyProperties(firePointAlarmPointBO,firePointAlarmPoint); return firePointAlarmPoint; } /** * 校验 能源消耗数据 * @param energyExpendDataBO * @return */ EnergyExpendDataBO verifyEnergyExpendData(@Validated EnergyExpendDataBO energyExpendDataBO){ EnergyExpendDataBO energyExpendData = new EnergyExpendDataBO(); BeanUtils.copyProperties(energyExpendDataBO,energyExpendData); return energyExpendData; } /** * 校验 企业车辆出入 * @param enterpriseCarComeRealTimeBO * @return */ EnterpriseCarComeRealTimeBO verifyEnterpriseCarRealTimeData(@Validated EnterpriseCarComeRealTimeBO enterpriseCarComeRealTimeBO){ EnterpriseCarComeRealTimeBO carComeRealTimeBO = new EnterpriseCarComeRealTimeBO(); BeanUtils.copyProperties(enterpriseCarComeRealTimeBO,carComeRealTimeBO); return carComeRealTimeBO; } /** * 校验 二道门人员出入 * @param twoDoorsInOutBO * @return */ TwoDoorsInOutBO verifyTwoDoorsInOut(@Validated TwoDoorsInOutBO twoDoorsInOutBO){ TwoDoorsInOutBO twoDoorsInOut = new TwoDoorsInOutBO(); BeanUtils.copyProperties(twoDoorsInOutBO,twoDoorsInOut); return twoDoorsInOut; } /** * 校验 二道门车间人员统计 * @param twoDoorsWorkShopTotalBO * @return */ TwoDoorsWorkShopTotalBO verifyTwoDoorsWorkshop(@Validated TwoDoorsWorkShopTotalBO twoDoorsWorkShopTotalBO){ TwoDoorsWorkShopTotalBO twoDoorsWorkShopTotal = new TwoDoorsWorkShopTotalBO(); BeanUtils.copyProperties(twoDoorsWorkShopTotalBO,twoDoorsWorkShopTotal); return twoDoorsWorkShopTotal; } /** * 校验 二道门报警 * @param electricRailBO * @return */ ElectricRailBO verifyTwoDoorsAlarm(@Validated ElectricRailBO electricRailBO){ ElectricRailBO twoDoorsAlarm = new ElectricRailBO(); BeanUtils.copyProperties(electricRailBO,twoDoorsAlarm); return twoDoorsAlarm; } /** * 校验 人员求助报警 * @param personPositionAlarmBO * @return */ PersonPositionAlarmBO verifyPersonPosition(@Validated PersonPositionAlarmBO personPositionAlarmBO){ PersonPositionAlarmBO personPositionAlarm = new PersonPositionAlarmBO(); BeanUtils.copyProperties(personPositionAlarmBO,personPositionAlarm); return personPositionAlarm; } /** * 校验 电子围栏 * @param electricRailBO * @return */ ElectricRailBO verifyElectricRail(@Validated ElectricRailBO electricRailBO){ ElectricRailBO electricRail = new ElectricRailBO(); BeanUtils.copyProperties(electricRailBO,electricRail); return electricRail; } /** *得到解密数据 * @param firmCheckDataBO * @param userMapper * @return */ public String getDecodeData(FirmCheckDataBO firmCheckDataBO,BaseUserMapper userMapper) { String cipherText = ""; BaseUser baseUser = userMapper.selectByPrimaryKey(firmCheckDataBO.getAppid()); RSAPrivateKey privateKey = null; try { privateKey = RSAUtil.getPrivateKey(baseUser.getRsaPrivateKey()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeySpecException e) { e.printStackTrace(); } //解密得到desKey String desKey = RSAUtil.privateDecrypt(firmCheckDataBO.getPublicKey(), privateKey); System.out.println("deskey:"+desKey); byte[] bytes = new byte[0]; try { bytes = RSAUtil.decryptBASE64(firmCheckDataBO.getEncryptData()); } catch (Exception e) { e.printStackTrace(); } //des解密 byte[] dataByte = DESUtil.desDecrypt(bytes, desKey); cipherText = new String(dataByte); return cipherText; } /** * 根据type值的不同,发往不同的队列 * @param checkData 基本业务字段 * @param decodeData 解密后data json */ String sendQueueByType(FirmCheckDataBO checkData,String decodeData,RabbitMqSender rabbitMqSender){ String returnClientJson = null; if(checkData != null && checkData.getDataType() != null){ switch (checkData.getDataType()){ case "Am0": // DcsDetectRealTimeBO dcsDetectRealTimeBO = JSON.parseObject(decodeData, DcsDetectRealTimeBO.class); List<DcsDetectRealTimeBO> dcsDetectRealTimeBOS = JSON.parseArray(decodeData, DcsDetectRealTimeBO.class); if(dcsDetectRealTimeBOS!= null&&dcsDetectRealTimeBOS.size()>0){ for (DcsDetectRealTimeBO dcsDetectRealTimeBO: dcsDetectRealTimeBOS) { DcsDetectRealTimeBO dcsDetectRealTime = verifyDcsDetectRealTimeData(dcsDetectRealTimeBO); returnClientJson = JSONArray.toJSONString(dcsDetectRealTime); rabbitMqSender.sendDetectRealTime(returnClientJson); } } break; case "Aa0": // DcsDetectAlarmDataBO dcsDetectAlarmDataBO = JSON.parseObject(decodeData, DcsDetectAlarmDataBO.class); List<DcsDetectAlarmDataBO> dcsDetectAlarmDataBOs = JSON.parseArray(decodeData, DcsDetectAlarmDataBO.class); if(dcsDetectAlarmDataBOs != null && dcsDetectAlarmDataBOs.size()>0){ for (DcsDetectAlarmDataBO dcsDetectAlarmDataBO: dcsDetectAlarmDataBOs) { DcsDetectAlarmDataBO dcsDetectAlarmData = verifyDcsDetectAlarmData(dcsDetectAlarmDataBO); returnClientJson = JSONArray.toJSONString(dcsDetectAlarmData); rabbitMqSender.sendDetectAlarm(returnClientJson); } } break; case "Xa0": // FirePointAlarmPointBO firePointAlarmPoint = JSON.parseObject(decodeData, FirePointAlarmPointBO.class); List<FirePointAlarmPointBO> firePointAlarmPoints = JSON.parseArray(decodeData, FirePointAlarmPointBO.class); if(firePointAlarmPoints != null && firePointAlarmPoints.size()>0){ for (FirePointAlarmPointBO firePointAlarmPoint: firePointAlarmPoints) { FirePointAlarmPointBO firePointAlarmPointBO = verifyFirePoint(firePointAlarmPoint); returnClientJson = JSONArray.toJSONString(firePointAlarmPointBO); rabbitMqSender.sendFirePoint(returnClientJson); } } break; case "Nm0": // EnergyExpendDataBO energyExpendData = JSON.parseObject(decodeData, EnergyExpendDataBO.class); List<EnergyExpendDataBO> energyExpendDatas = JSON.parseArray(decodeData, EnergyExpendDataBO.class); if(energyExpendDatas != null && energyExpendDatas.size()>0){ if(energyExpendDatas!=null &&energyExpendDatas.size()>0){ for (EnergyExpendDataBO energyExpendData: energyExpendDatas) { EnergyExpendDataBO energyExpendDataBO = verifyEnergyExpendData(energyExpendData); returnClientJson = JSONArray.toJSONString(energyExpendDataBO); rabbitMqSender.sendEnergyExpend(returnClientJson); } } } break; case "Fm2": // EnterpriseOnDutyBO enterpriseOnDuty = JSON.parseObject(decodeData, EnterpriseOnDutyBO.class); List<EnterpriseCarComeRealTimeBO> enterpriseCarComeRealTimeBOS = JSON.parseArray(decodeData, EnterpriseCarComeRealTimeBO.class); if(enterpriseCarComeRealTimeBOS != null && enterpriseCarComeRealTimeBOS.size()>0){ for (EnterpriseCarComeRealTimeBO enterpriseCarComeRealTimeBO: enterpriseCarComeRealTimeBOS) { EnterpriseCarComeRealTimeBO enterpriseCarComeRealTimeBO1 = verifyEnterpriseCarRealTimeData(enterpriseCarComeRealTimeBO); returnClientJson = JSONArray.toJSONString(enterpriseCarComeRealTimeBO1); rabbitMqSender.sendEnterpriseOnDuty(returnClientJson); } } break; case "Fm1": // TwoDoorsInOutBO twoDoorsInOut = JSON.parseObject(decodeData, TwoDoorsInOutBO.class); List<TwoDoorsInOutBO> twoDoorsInOuts = JSON.parseArray(decodeData, TwoDoorsInOutBO.class); if(twoDoorsInOuts != null && twoDoorsInOuts.size()>0){ for (TwoDoorsInOutBO twoDoorsInOut: twoDoorsInOuts) { TwoDoorsInOutBO twoDoorsInOutBO = verifyTwoDoorsInOut(twoDoorsInOut); returnClientJson = JSONArray.toJSONString(twoDoorsInOutBO); rabbitMqSender.sendTwoDoorsInout(returnClientJson); } } break; case "Fm0": // TwoDoorsWorkShopTotalBO twoDoorsWorkShopTotal = JSON.parseObject(decodeData, TwoDoorsWorkShopTotalBO.class); List<TwoDoorsWorkShopTotalBO> twoDoorsWorkShopTotals = JSON.parseArray(decodeData, TwoDoorsWorkShopTotalBO.class); if(twoDoorsWorkShopTotals!= null && twoDoorsWorkShopTotals.size()>0){ for (TwoDoorsWorkShopTotalBO twoDoorsWorkShopTotal: twoDoorsWorkShopTotals) { TwoDoorsWorkShopTotalBO twoDoorsWorkShopTotalBO = verifyTwoDoorsWorkshop(twoDoorsWorkShopTotal); returnClientJson = JSONArray.toJSONString(twoDoorsWorkShopTotalBO); rabbitMqSender.sendTwoDoorsWorkshop(returnClientJson); } } break; case "Fa3": // TwoDoorsAlarmBO twoDoorsAlarm = JSON.parseObject(decodeData, TwoDoorsAlarmBO.class); List<PersonPositionAlarmBO> personPositionAlarmBOS = JSON.parseArray(decodeData, PersonPositionAlarmBO.class); if(personPositionAlarmBOS!= null && personPositionAlarmBOS.size()>0){ for (PersonPositionAlarmBO personPositionAlarmBO: personPositionAlarmBOS) { PersonPositionAlarmBO personPositionAlarmBO1 = verifyPersonPosition(personPositionAlarmBO); returnClientJson = JSONArray.toJSONString(personPositionAlarmBO1); rabbitMqSender.sendTwoDoorsAlarm(returnClientJson); } } break; case "Fa4": // TwoDoorsAlarmBO twoDoorsAlarm = JSON.parseObject(decodeData, TwoDoorsAlarmBO.class); List<ElectricRailBO> electricRailBOS = JSON.parseArray(decodeData, ElectricRailBO.class); if(electricRailBOS!= null && electricRailBOS.size()>0){ for (ElectricRailBO electricRailBO: electricRailBOS) { ElectricRailBO electricRail = verifyElectricRail(electricRailBO); returnClientJson = JSONArray.toJSONString(electricRail); rabbitMqSender.sendElectronicRail(returnClientJson); } } break; default: throw new RuntimeException("dataType传值有误"); } } return returnClientJson; } }
MyServerValidateHandler
package com.zhetang.netty; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.zhetang.config.QueueConfig; import com.zhetang.mapper.mysqlMapper.BaseUserMapper; import com.zhetang.model.bo.realtime.FirmCheckDataBO; import com.zhetang.model.mysql.lvms.BaseUser; import com.zhetang.model.pojo.DataResult; import com.zhetang.model.pojo.ErrorResult; import com.zhetang.rabbitmq.RabbitMqSender; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.CharsetUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; import javax.annotation.PostConstruct; import java.nio.charset.Charset; /** * Created with IntelliJ IDEA. * User:wq * Date:2021/4/26 * Time: 15:35 * Description: No Description */ @Component @Slf4j public class MyServerValidateHandler extends ChannelInboundHandlerAdapter { @Autowired private BaseUserMapper userMapper; private static MyServerValidateHandler myServerValidateHandler; @PostConstruct public void init() { myServerValidateHandler = this; myServerValidateHandler.userMapper = this.userMapper; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FirmCheckDataBO checkData = null; FirmCheckDataBO checkDataBO = null; DataResult dataResult = null; BaseUserMapper userMapper = myServerValidateHandler.userMapper; ByteBuf byteBuf = (ByteBuf) msg; String json = byteBuf.toString(CharsetUtil.UTF_8); log.info(ctx.channel().remoteAddress()+"发送消息:"+byteBuf.toString(CharsetUtil.UTF_8)); try{ checkDataBO = JSONObject.parseObject(json, FirmCheckDataBO.class); checkData = verifyCheckData(checkDataBO); }catch (RuntimeException e){ if (e.getCause() != null) { log.error(e.getCause().getCause().toString()); e.printStackTrace(); if(checkData != null|| checkDataBO != null){ dataResult = new DataResult(false, checkDataBO.getDataId(),new ErrorResult(e.getCause().getCause().toString())); } else { dataResult = new DataResult(false, "dataId不能为空",new ErrorResult(e.getCause().getCause().toString())); } // ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), CharsetUtil.UTF_8)); ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), Charset.forName("GBK"))); throw new RuntimeException("字段未填,连接失败!!!"); } } try{ BaseUser baseUser = userMapper.selectByPrimaryKey(checkData.getAppid()); if(baseUser == null){ throw new RuntimeException("用户不存在"); } ctx.fireChannelRead(msg); }catch (RuntimeException e){ e.printStackTrace(); if(checkData != null){ dataResult = new DataResult(false, checkData.getDataId(), new ErrorResult("未授权的访问")); }else { dataResult = new DataResult(false, "dataId不能为空", new ErrorResult("未授权的访问")); } // ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), CharsetUtil.UTF_8)); ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), Charset.forName("GBK"))); throw new RuntimeException("认证token有误!!!!!!"); } } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { //发送消息给客户端 // ctx.writeAndFlush(Unpooled.copiedBuffer("@@", CharsetUtil.UTF_8)); ctx.writeAndFlush(Unpooled.copiedBuffer("@@", Charset.forName("GBK"))); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { //发生异常,关闭通道 log.error("ctx检测到"+ctx.channel().remoteAddress()+"异常!!!!!!",cause); ctx.close(); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { log.error("ctx检测到"+ctx.channel().remoteAddress()+"已断线!!!!!!"); super.channelInactive(ctx); } FirmCheckDataBO verifyCheckData(@Validated FirmCheckDataBO firmCheckDataBO){ FirmCheckDataBO checkDataBO = new FirmCheckDataBO(); BeanUtils.copyProperties(firmCheckDataBO,checkDataBO); return checkDataBO; } }
Application
package com.zhetang; import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import com.zhetang.netty.MyServer; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling @ConfigurationProperties public class GetsqlserverApplication { public static void main(String[] args) { SpringApplication.run(GetsqlserverApplication.class, args); MyServer.init(); } @Bean public HttpMessageConverters fastJsonHttpMessageConverters() { FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); fastConverter.setFastJsonConfig(fastJsonConfig); HttpMessageConverter<?> converter = fastConverter; return new HttpMessageConverters(converter); } }
利用分隔符@@避免粘包半包现象
myServer
package com.zhetang.netty; import com.zhetang.mapper.mysqlMapper.BaseUserMapper; 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.string.StringEncoder; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.nio.charset.Charset; import java.util.concurrent.TimeUnit; /** * Created with IntelliJ IDEA. * User:wq * Date:2021/4/19 * Time: 20:12 * Description: No Description */ @Slf4j @Component public class MyServer { // @Value("${my.server.port}") // private static Integer port; @Resource private BaseUserMapper userMapper; private static final Integer portt =8082; public static void init(){ //创建两个线程组 boosGroup、workerGroup EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { //创建服务端的启动对象,设置参数 ServerBootstrap bootstrap = new ServerBootstrap(); //设置两个线程组boosGroup和workerGroup bootstrap.group(bossGroup, workerGroup) //设置服务端通道实现类型 .channel(NioServerSocketChannel.class) //设置线程队列得到连接个数 .option(ChannelOption.SO_BACKLOG, 128) //设置保持活动连接状态 .childOption(ChannelOption.SO_KEEPALIVE, true) //使用匿名内部类的形式初始化通道对象 // .childHandler(new ChannelInitializer<SocketChannel>() { // @Override // protected void initChannel(SocketChannel socketChannel) throws Exception { // 给pipeline管道设置处理器 // socketChannel.pipeline().addFirst(new MyServerValidateHandler()); // socketChannel.pipeline().addLast(new MyServerHandler()); // // } // });//给workerGroup的EventLoop对应的管道设置处理器 .childHandler(new SocketServerInitializer()); log.info("实时数据采集服务端准备就绪!!!!!!"); //绑定端口号,启动服务端 ChannelFuture channelFuture = null; try { channelFuture = bootstrap.bind(portt).sync(); } catch (InterruptedException e) { e.printStackTrace(); } //对关闭通道进行监听 try { channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { //创建两个线程组 boosGroup、workerGroup EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { //创建服务端的启动对象,设置参数 ServerBootstrap bootstrap = new ServerBootstrap(); //设置两个线程组boosGroup和workerGroup bootstrap.group(bossGroup, workerGroup) //设置服务端通道实现类型 .channel(NioServerSocketChannel.class) //设置线程队列得到连接个数 .option(ChannelOption.SO_BACKLOG, 128) //设置保持活动连接状态 .childOption(ChannelOption.SO_KEEPALIVE, true) //使用匿名内部类的形式初始化通道对象 .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { //给pipeline管道设置处理器 socketChannel.pipeline().addFirst(new MyServerValidateHandler()); socketChannel.pipeline().addLast(new MyServerHandler()); } });//给workerGroup的EventLoop对应的管道设置处理器 log.info("实时数据采集服务端准备就绪!!!!!!"); //绑定端口号,启动服务端 ChannelFuture channelFuture = bootstrap.bind(portt).sync(); //对关闭通道进行监听 channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
SocketServerInitializer
package com.zhetang.netty; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; /** * Created with IntelliJ IDEA. * User:wq * Date:2021/5/8 * Time: 18:20 * Description: No Description */ public class SocketServerInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { // 告诉DelimiterBasedFrameDecoder以$_作为分隔符 ByteBuf delimiter = Unpooled.copiedBuffer("@@".getBytes()); ChannelPipeline pipeline = socketChannel.pipeline(); //这里的1024,表示单条消息的最大长度,当达到长度后,还没有找到分隔符,则抛出TooLongFrameException // pipeline.addLast(new LengthFieldBasedFrameDecoder(60*1024,0,2)); // pipeline.addLast(new DelimiterBasedFrameDecoder(10*1024,delimiter)); pipeline.addLast(new DelimiterBasedFrameDecoder(1024*1024*8,delimiter)); pipeline.addLast(new MyServerValidateHandler()); pipeline.addLast(new MyServerHandler()); } }
MyServerValidateHandler
package com.zhetang.netty; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.zhetang.config.QueueConfig; import com.zhetang.mapper.mysqlMapper.BaseUserMapper; import com.zhetang.model.bo.realtime.FirmCheckDataBO; import com.zhetang.model.mysql.lvms.BaseUser; import com.zhetang.model.pojo.DataResult; import com.zhetang.model.pojo.ErrorResult; import com.zhetang.rabbitmq.RabbitMqSender; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.CharsetUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; import javax.annotation.PostConstruct; import java.nio.charset.Charset; /** * Created with IntelliJ IDEA. * User:wq * Date:2021/4/26 * Time: 15:35 * Description: No Description */ @Component @Slf4j public class MyServerValidateHandler extends ChannelInboundHandlerAdapter { @Autowired private BaseUserMapper userMapper; private static MyServerValidateHandler myServerValidateHandler; @PostConstruct public void init() { myServerValidateHandler = this; myServerValidateHandler.userMapper = this.userMapper; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FirmCheckDataBO checkData = null; FirmCheckDataBO checkDataBO = null; DataResult dataResult = null; BaseUserMapper userMapper = myServerValidateHandler.userMapper; ByteBuf byteBuf = (ByteBuf) msg; String json = byteBuf.toString(CharsetUtil.UTF_8); log.info(ctx.channel().remoteAddress()+"发送消息:"+byteBuf.toString(CharsetUtil.UTF_8)); try{ checkDataBO = JSONObject.parseObject(json, FirmCheckDataBO.class); checkData = verifyCheckData(checkDataBO); }catch (RuntimeException e){ if (e.getCause() != null) { log.error(e.getCause().getCause().toString()); e.printStackTrace(); if(checkData != null|| checkDataBO != null){ dataResult = new DataResult(false, checkDataBO.getDataId(),new ErrorResult(e.getCause().getCause().toString())); } else { dataResult = new DataResult(false, "dataId不能为空",new ErrorResult(e.getCause().getCause().toString())); } ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), CharsetUtil.UTF_8)); // ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), Charset.forName("GBK"))); throw new RuntimeException("字段未填,连接失败!!!"); } } try{ BaseUser baseUser = userMapper.selectByPrimaryKey(checkData.getAppid()); if(baseUser == null){ throw new RuntimeException("用户不存在"); } ctx.fireChannelRead(msg); }catch (RuntimeException e){ e.printStackTrace(); if(checkData != null){ dataResult = new DataResult(false, checkData.getDataId(), new ErrorResult("未授权的访问")); }else { dataResult = new DataResult(false, "dataId不能为空", new ErrorResult("未授权的访问")); } ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), CharsetUtil.UTF_8)); // ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), Charset.forName("GBK"))); throw new RuntimeException("认证token有误!!!!!!"); } } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { //发送消息给客户端 ctx.writeAndFlush(Unpooled.copiedBuffer("@@", CharsetUtil.UTF_8)); // ctx.writeAndFlush(Unpooled.copiedBuffer("@@", Charset.forName("GBK"))); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { //发生异常,关闭通道 log.error("ctx检测到"+ctx.channel().remoteAddress()+"异常!!!!!!",cause); ctx.close(); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { log.error("ctx检测到"+ctx.channel().remoteAddress()+"已断线!!!!!!"); super.channelInactive(ctx); } FirmCheckDataBO verifyCheckData(@Validated FirmCheckDataBO firmCheckDataBO){ FirmCheckDataBO checkDataBO = new FirmCheckDataBO(); BeanUtils.copyProperties(firmCheckDataBO,checkDataBO); return checkDataBO; } }
MyServerHandler
package com.zhetang.netty; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.zhetang.config.QueueConfig; import com.zhetang.mapper.mysqlMapper.BaseUserMapper; import com.zhetang.model.bo.realtime.*; import com.zhetang.model.mysql.lvms.BaseUser; import com.zhetang.model.pojo.DataResult; import com.zhetang.model.pojo.ErrorResult; import com.zhetang.rabbitmq.RabbitMqSender; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.CharsetUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; import javax.annotation.PostConstruct; import java.nio.charset.Charset; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPrivateKey; import java.security.spec.InvalidKeySpecException; import java.util.List; /** * Created with IntelliJ IDEA. * User:wq * Date:2021/4/19 * Time: 20:13 * Description: No Description */ /** * 自定义的Handler需要继承Netty规定好的HandlerAdapter * 才能被Netty框架所关联,有点类似SpringMVC的适配器模式 **/ @Component @Slf4j public class MyServerHandler extends ChannelInboundHandlerAdapter { @Autowired private BaseUserMapper userMapper; private static MyServerHandler myServerHandler; @Autowired private RabbitMqSender rabbitMqSender; @Autowired private QueueConfig queueConfig; @PostConstruct public void init() { myServerHandler = this; myServerHandler.userMapper = this.userMapper; myServerHandler.rabbitMqSender =this.rabbitMqSender; myServerHandler.queueConfig = this.queueConfig; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { BaseUserMapper userMapper = myServerHandler.userMapper; RabbitMqSender rabbitMqSender = myServerHandler.rabbitMqSender; //获取客户端发送过来的消息 FirmCheckDataBO data = null; FirmCheckDataBO checkData = null; String returnClientJson = null; String decodeData = null; ByteBuf byteBuf = (ByteBuf) msg; try { String json = byteBuf.toString(CharsetUtil.UTF_8); FirmCheckDataBO checkDataBO = JSONObject.parseObject(json, FirmCheckDataBO.class); checkData = verifyCheckData(checkDataBO); decodeData = getDecodeData(checkDataBO, userMapper); log.info("解密后:"+decodeData); }catch (RuntimeException e){ e.printStackTrace(); DataResult dataResult = new DataResult(false, checkData.getDataId(), new ErrorResult("未授权的访问")); ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), CharsetUtil.UTF_8)); //ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), Charset.forName("GBK"))); throw new RuntimeException("认证token有误!!!!!!"); } try{ //验证企业数据是否已填 returnClientJson = sendQueueByType(checkData, decodeData,rabbitMqSender); DataResult dataResult = new DataResult(true, checkData.getDataId()); ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), CharsetUtil.UTF_8)); // ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), Charset.forName("GBK"))); }catch (RuntimeException e) { e.printStackTrace(); if (e.getCause() != null) { log.error(e.getCause().getCause().toString()); DataResult dataResult = new DataResult(false, checkData.getDataId(),new ErrorResult(e.getCause().getCause().toString())); ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), CharsetUtil.UTF_8)); // ctx.writeAndFlush(Unpooled.copiedBuffer( JSON.toJSONString(dataResult), Charset.forName("GBK"))); throw new RuntimeException("字段未填!!!!!!"); }else { DataResult dataResult = new DataResult(false, checkData.getDataId(),new ErrorResult(e.toString())); ctx.writeAndFlush(Unpooled.copiedBuffer(JSON.toJSONString(dataResult), CharsetUtil.UTF_8)); // ctx.writeAndFlush(Unpooled.copiedBuffer( JSON.toJSONString(dataResult), Charset.forName("GBK"))); throw new RuntimeException("dataType传值有误!!!!!!"); } } } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { //发送消息给客户端 ctx.writeAndFlush(Unpooled.copiedBuffer("@@", CharsetUtil.UTF_8)); // ctx.writeAndFlush(Unpooled.copiedBuffer("@@", Charset.forName("GBK"))); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { //发生异常,关闭通道 log.error("ctx检测到"+ctx.channel().remoteAddress()+"异常!!!!!!",cause); ctx.close(); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { log.error("ctx检测到"+ctx.channel().remoteAddress()+"已断线!!!!!!"); super.channelInactive(ctx); } FirmCheckDataBO verifyCheckData(@Validated FirmCheckDataBO firmCheckDataBO){ FirmCheckDataBO checkDataBO = new FirmCheckDataBO(); BeanUtils.copyProperties(firmCheckDataBO,checkDataBO); return checkDataBO; } /** * 校验 安全监测点位、工艺监测DCS监测点位实时数据 * @param dcsDetectRealTimeBO * @return */ DcsDetectRealTimeBO verifyDcsDetectRealTimeData(@Validated DcsDetectRealTimeBO dcsDetectRealTimeBO){ DcsDetectRealTimeBO detectRealTimeBO = new DcsDetectRealTimeBO(); BeanUtils.copyProperties(dcsDetectRealTimeBO,detectRealTimeBO); return detectRealTimeBO; } /** * 校验 安全监测点位、生产⼯艺(治污工艺)DCS监测点位报警数据 * @param dcsDetectAlarmDataBO * @return */ DcsDetectAlarmDataBO verifyDcsDetectAlarmData(@Validated DcsDetectAlarmDataBO dcsDetectAlarmDataBO){ DcsDetectAlarmDataBO detectAlarmDataBO = new DcsDetectAlarmDataBO(); BeanUtils.copyProperties(dcsDetectAlarmDataBO,detectAlarmDataBO); return detectAlarmDataBO; } /** * 校验 消防点位报警数据 * @param firePointAlarmPointBO * @return */ FirePointAlarmPointBO verifyFirePoint(@Validated FirePointAlarmPointBO firePointAlarmPointBO){ FirePointAlarmPointBO firePointAlarmPoint = new FirePointAlarmPointBO(); BeanUtils.copyProperties(firePointAlarmPointBO,firePointAlarmPoint); return firePointAlarmPoint; } /** * 校验 能源消耗数据 * @param energyExpendDataBO * @return */ EnergyExpendDataBO verifyEnergyExpendData(@Validated EnergyExpendDataBO energyExpendDataBO){ EnergyExpendDataBO energyExpendData = new EnergyExpendDataBO(); BeanUtils.copyProperties(energyExpendDataBO,energyExpendData); return energyExpendData; } /** * 校验 企业车辆出入 * @param enterpriseCarComeRealTimeBO * @return */ EnterpriseCarComeRealTimeBO verifyEnterpriseCarRealTimeData(@Validated EnterpriseCarComeRealTimeBO enterpriseCarComeRealTimeBO){ EnterpriseCarComeRealTimeBO carComeRealTimeBO = new EnterpriseCarComeRealTimeBO(); BeanUtils.copyProperties(enterpriseCarComeRealTimeBO,carComeRealTimeBO); return carComeRealTimeBO; } /** * 校验 二道门人员出入 * @param twoDoorsInOutBO * @return */ TwoDoorsInOutBO verifyTwoDoorsInOut(@Validated TwoDoorsInOutBO twoDoorsInOutBO){ TwoDoorsInOutBO twoDoorsInOut = new TwoDoorsInOutBO(); BeanUtils.copyProperties(twoDoorsInOutBO,twoDoorsInOut); return twoDoorsInOut; } /** * 校验 二道门车间人员统计 * @param twoDoorsWorkShopTotalBO * @return */ TwoDoorsWorkShopTotalBO verifyTwoDoorsWorkshop(@Validated TwoDoorsWorkShopTotalBO twoDoorsWorkShopTotalBO){ TwoDoorsWorkShopTotalBO twoDoorsWorkShopTotal = new TwoDoorsWorkShopTotalBO(); BeanUtils.copyProperties(twoDoorsWorkShopTotalBO,twoDoorsWorkShopTotal); return twoDoorsWorkShopTotal; } /** * 校验 二道门报警 * @param electricRailBO * @return */ ElectricRailBO verifyTwoDoorsAlarm(@Validated ElectricRailBO electricRailBO){ ElectricRailBO twoDoorsAlarm = new ElectricRailBO(); BeanUtils.copyProperties(electricRailBO,twoDoorsAlarm); return twoDoorsAlarm; } /** * 校验 人员求助报警 * @param personPositionAlarmBO * @return */ PersonPositionAlarmBO verifyPersonPosition(@Validated PersonPositionAlarmBO personPositionAlarmBO){ PersonPositionAlarmBO personPositionAlarm = new PersonPositionAlarmBO(); BeanUtils.copyProperties(personPositionAlarmBO,personPositionAlarm); return personPositionAlarm; } /** * 校验 电子围栏 * @param electricRailBO * @return */ ElectricRailBO verifyElectricRail(@Validated ElectricRailBO electricRailBO){ ElectricRailBO electricRail = new ElectricRailBO(); BeanUtils.copyProperties(electricRailBO,electricRail); return electricRail; } /** *得到解密数据 * @param firmCheckDataBO * @param userMapper * @return */ public String getDecodeData(FirmCheckDataBO firmCheckDataBO,BaseUserMapper userMapper) { String cipherText = ""; BaseUser baseUser = userMapper.selectByPrimaryKey(firmCheckDataBO.getAppid()); RSAPrivateKey privateKey = null; try { privateKey = RSAUtil.getPrivateKey(baseUser.getRsaPrivateKey()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeySpecException e) { e.printStackTrace(); } //解密得到desKey String desKey = RSAUtil.privateDecrypt(firmCheckDataBO.getPublicKey(), privateKey); System.out.println("deskey:"+desKey); byte[] bytes = new byte[0]; try { bytes = RSAUtil.decryptBASE64(firmCheckDataBO.getEncryptData()); } catch (Exception e) { e.printStackTrace(); } //des解密 byte[] dataByte = DESUtil.desDecrypt(bytes, desKey); cipherText = new String(dataByte); return cipherText; } /** * 根据type值的不同,发往不同的队列 * @param checkData 基本业务字段 * @param decodeData 解密后data json */ String sendQueueByType(FirmCheckDataBO checkData,String decodeData,RabbitMqSender rabbitMqSender){ String returnClientJson = null; String jsonString = null; if(checkData != null && checkData.getDataType() != null){ switch (checkData.getDataType()){ case "Am0": // DcsDetectRealTimeBO dcsDetectRealTimeBO = JSON.parseObject(decodeData, DcsDetectRealTimeBO.class); List<DcsDetectRealTimeBO> dcsDetectRealTimeBOS = JSON.parseArray(decodeData, DcsDetectRealTimeBO.class); if(dcsDetectRealTimeBOS!= null&&dcsDetectRealTimeBOS.size()>0){ for (DcsDetectRealTimeBO dcsDetectRealTimeBO: dcsDetectRealTimeBOS) { DcsDetectRealTimeBO dcsDetectRealTime = verifyDcsDetectRealTimeData(dcsDetectRealTimeBO); jsonString = JSONArray.toJSONString(dcsDetectRealTime); checkData.setEncryptData(jsonString); returnClientJson = JSONArray.toJSONString(checkData); rabbitMqSender.sendDetectRealTime(returnClientJson); } } break; case "Aa0": // DcsDetectAlarmDataBO dcsDetectAlarmDataBO = JSON.parseObject(decodeData, DcsDetectAlarmDataBO.class); List<DcsDetectAlarmDataBO> dcsDetectAlarmDataBOs = JSON.parseArray(decodeData, DcsDetectAlarmDataBO.class); if(dcsDetectAlarmDataBOs != null && dcsDetectAlarmDataBOs.size()>0){ for (DcsDetectAlarmDataBO dcsDetectAlarmDataBO: dcsDetectAlarmDataBOs) { DcsDetectAlarmDataBO dcsDetectAlarmData = verifyDcsDetectAlarmData(dcsDetectAlarmDataBO); jsonString = JSONArray.toJSONString(dcsDetectAlarmData); checkData.setEncryptData(jsonString); returnClientJson = JSON.toJSONString(checkData); rabbitMqSender.sendDetectAlarm(returnClientJson); } } break; case "Xa0": // FirePointAlarmPointBO firePointAlarmPoint = JSON.parseObject(decodeData, FirePointAlarmPointBO.class); List<FirePointAlarmPointBO> firePointAlarmPoints = JSON.parseArray(decodeData, FirePointAlarmPointBO.class); if(firePointAlarmPoints != null && firePointAlarmPoints.size()>0){ for (FirePointAlarmPointBO firePointAlarmPoint: firePointAlarmPoints) { FirePointAlarmPointBO firePointAlarmPointBO = verifyFirePoint(firePointAlarmPoint); jsonString = JSONArray.toJSONString(firePointAlarmPointBO); checkData.setEncryptData(jsonString); returnClientJson = JSONArray.toJSONString(checkData); rabbitMqSender.sendFirePoint(returnClientJson); } } break; case "Nm0": // EnergyExpendDataBO energyExpendData = JSON.parseObject(decodeData, EnergyExpendDataBO.class); List<EnergyExpendDataBO> energyExpendDatas = JSON.parseArray(decodeData, EnergyExpendDataBO.class); if(energyExpendDatas != null && energyExpendDatas.size()>0){ if(energyExpendDatas!=null &&energyExpendDatas.size()>0){ for (EnergyExpendDataBO energyExpendData: energyExpendDatas) { EnergyExpendDataBO energyExpendDataBO = verifyEnergyExpendData(energyExpendData); jsonString = JSONArray.toJSONString(energyExpendDataBO); checkData.setEncryptData(jsonString); returnClientJson = JSONArray.toJSONString(checkData); rabbitMqSender.sendEnergyExpend(returnClientJson); } } } break; case "Fm2": // EnterpriseOnDutyBO enterpriseOnDuty = JSON.parseObject(decodeData, EnterpriseOnDutyBO.class); List<EnterpriseCarComeRealTimeBO> enterpriseCarComeRealTimeBOS = JSON.parseArray(decodeData, EnterpriseCarComeRealTimeBO.class); if(enterpriseCarComeRealTimeBOS != null && enterpriseCarComeRealTimeBOS.size()>0){ for (EnterpriseCarComeRealTimeBO enterpriseCarComeRealTimeBO: enterpriseCarComeRealTimeBOS) { EnterpriseCarComeRealTimeBO enterpriseCarComeRealTimeBO1 = verifyEnterpriseCarRealTimeData(enterpriseCarComeRealTimeBO); jsonString = JSONArray.toJSONString(enterpriseCarComeRealTimeBO1); checkData.setEncryptData(jsonString); returnClientJson = JSONArray.toJSONString(checkData); rabbitMqSender.sendEnterpriseOnDuty(returnClientJson); } } break; case "Fm1": // TwoDoorsInOutBO twoDoorsInOut = JSON.parseObject(decodeData, TwoDoorsInOutBO.class); List<TwoDoorsInOutBO> twoDoorsInOuts = JSON.parseArray(decodeData, TwoDoorsInOutBO.class); if(twoDoorsInOuts != null && twoDoorsInOuts.size()>0){ for (TwoDoorsInOutBO twoDoorsInOut: twoDoorsInOuts) { TwoDoorsInOutBO twoDoorsInOutBO = verifyTwoDoorsInOut(twoDoorsInOut); jsonString = JSONArray.toJSONString(twoDoorsInOutBO); checkData.setEncryptData(jsonString); returnClientJson = JSONArray.toJSONString(checkData); rabbitMqSender.sendTwoDoorsInout(returnClientJson); } } break; case "Fm0": // TwoDoorsWorkShopTotalBO twoDoorsWorkShopTotal = JSON.parseObject(decodeData, TwoDoorsWorkShopTotalBO.class); List<TwoDoorsWorkShopTotalBO> twoDoorsWorkShopTotals = JSON.parseArray(decodeData, TwoDoorsWorkShopTotalBO.class); if(twoDoorsWorkShopTotals!= null && twoDoorsWorkShopTotals.size()>0){ for (TwoDoorsWorkShopTotalBO twoDoorsWorkShopTotal: twoDoorsWorkShopTotals) { TwoDoorsWorkShopTotalBO twoDoorsWorkShopTotalBO = verifyTwoDoorsWorkshop(twoDoorsWorkShopTotal); jsonString = JSONArray.toJSONString(twoDoorsWorkShopTotalBO); checkData.setEncryptData(jsonString); returnClientJson = JSONArray.toJSONString(checkData); rabbitMqSender.sendTwoDoorsWorkshop(returnClientJson); } } break; case "Fa3": // TwoDoorsAlarmBO twoDoorsAlarm = JSON.parseObject(decodeData, TwoDoorsAlarmBO.class); List<PersonPositionAlarmBO> personPositionAlarmBOS = JSON.parseArray(decodeData, PersonPositionAlarmBO.class); if(personPositionAlarmBOS!= null && personPositionAlarmBOS.size()>0){ for (PersonPositionAlarmBO personPositionAlarmBO: personPositionAlarmBOS) { PersonPositionAlarmBO personPositionAlarmBO1 = verifyPersonPosition(personPositionAlarmBO); jsonString = JSONArray.toJSONString(personPositionAlarmBO1); checkData.setEncryptData(jsonString); returnClientJson = JSONArray.toJSONString(checkData); rabbitMqSender.sendTwoDoorsAlarm(returnClientJson); } } break; case "Fa4": // TwoDoorsAlarmBO twoDoorsAlarm = JSON.parseObject(decodeData, TwoDoorsAlarmBO.class); List<ElectricRailBO> electricRailBOS = JSON.parseArray(decodeData, ElectricRailBO.class); if(electricRailBOS!= null && electricRailBOS.size()>0){ for (ElectricRailBO electricRailBO: electricRailBOS) { ElectricRailBO electricRail = verifyElectricRail(electricRailBO); jsonString = JSONArray.toJSONString(electricRail); checkData.setEncryptData(jsonString); returnClientJson = JSONArray.toJSONString(checkData); rabbitMqSender.sendElectronicRail(returnClientJson); } } break; default: throw new RuntimeException("dataType传值有误"); } } return returnClientJson; } }
DESUtil
package com.zhetang.netty; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.IvParameterSpec; import java.security.NoSuchAlgorithmException; /** * Created with IntelliJ IDEA. * User: lzx * Date: 2020/6/23 * Time: 9:29 * Description: No Description */ public class DESUtil { /** * 生成KEY */ public static byte[] getKey(){ KeyGenerator keyGenerator = null; try { keyGenerator = KeyGenerator.getInstance("DES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); System.out.println("----------------KEY生成失败!"); return null; } keyGenerator.init(56); SecretKey secretKey = keyGenerator.generateKey(); byte[] byteKey = secretKey.getEncoded(); return byteKey; } /** * DES加密 * * @param context * @return */ public static byte[] desEncrypt(String context, String key) { try { // KEY转换 DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8")); SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES"); SecretKey conventSecretKey = secretKeyFactory.generateSecret(desKeySpec); // 加密 Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, conventSecretKey, new IvParameterSpec(key.getBytes("UTF-8"))); return cipher.doFinal(context.getBytes("UTF-8")); } catch (Throwable e) { e.printStackTrace(); return null; } } /** * DES解密 * * @param context * @return */ public static byte[] desDecrypt(byte[] context, String key) { try { // KEY转换 DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8")); SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES"); SecretKey conventSecretKey = secretKeyFactory.generateSecret(desKeySpec); // 解密 Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, conventSecretKey, new IvParameterSpec(key.getBytes("UTF-8"))); return cipher.doFinal(context); } catch (Throwable e) { e.printStackTrace(); return null; } } }
RSAUtil
package com.zhetang.netty; import org.apache.commons.codec.binary.Base64; import org.apache.tomcat.util.http.fileupload.IOUtils; import javax.crypto.Cipher; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.FileWriter; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import org.apache.commons.codec.binary.Base64; /** * Created with IntelliJ IDEA. * User: lzx * Date: 2020/6/23 * Time: 9:30 * Description: No Description */ public class RSAUtil { /** * 转密钥字符串(base64编码) * * @return */ public static String getKeyString(Key key) throws Exception { byte[] keyBytes = key.getEncoded(); // String s = new String(Base64.encodeBase64(keyBytes)); String s = new String(Base64.encodeBase64(keyBytes)); return s; } /** * 得到公钥 * @param publicKey 密钥字符串(经过base64编码) * @throws Exception */ public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException { //通过X509编码的Key指令获得公钥对象 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey)); RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec); return key; } /** * 得到私钥 * @param privateKey 密钥字符串(经过base64编码) * @throws Exception */ public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException { //通过PKCS#8编码的Key指令获得私钥对象 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)); RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec); return key; } /** * 生成密钥对 * @param pubfilePath 公钥存放的文件路径 * @param prifilePath 私钥存放的文件路径 */ public static void genKeyPair(String pubfilePath, String prifilePath) { // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象 KeyPairGenerator keyPairGen = null; try { keyPairGen = KeyPairGenerator.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } // 初始化密钥对生成器,密钥大小为96-1024位 keyPairGen.initialize(1024, new SecureRandom()); // 生成一个密钥对,保存在keyPair中 KeyPair keyPair = keyPairGen.generateKeyPair(); // 得到私钥 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到公钥 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); try { // 得到公钥字符串 String publicKeyString = getKeyString(publicKey); // 得到私钥字符串 String privateKeyString = getKeyString(privateKey); // 将密钥对写入到文件 FileWriter pubfw = new FileWriter(pubfilePath); FileWriter prifw = new FileWriter(prifilePath); BufferedWriter pubbw = new BufferedWriter(pubfw); BufferedWriter pribw = new BufferedWriter(prifw); pubbw.write(publicKeyString); pribw.write(privateKeyString); pubbw.flush(); pubbw.close(); pubfw.close(); pribw.flush(); pribw.close(); prifw.close(); } catch (Exception e) { e.printStackTrace(); } } /** * 公钥加密 * @param data 需要加密的内容 * @param publicKey 公钥 * @return */ public static String publicEncrypt(String data, RSAPublicKey publicKey){ try{ Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return new String(Base64.encodeBase64(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes("UTF-8"), publicKey.getModulus().bitLength()))); }catch(Exception e){ throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e); } } /** * 私钥解密 * @param data 需要加密的内容 * @param privateKey 私钥 * @return */ public static String privateDecrypt(String data, RSAPrivateKey privateKey){ try{ Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), "UTF-8"); }catch(Exception e){ throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e); } } private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){ int maxBlock = 0; if(opmode == Cipher.DECRYPT_MODE){ maxBlock = keySize / 8; }else{ maxBlock = keySize / 8 - 11; } ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] buff; int i = 0; try{ while(datas.length > offSet){ if(datas.length-offSet > maxBlock){ buff = cipher.doFinal(datas, offSet, maxBlock); }else{ buff = cipher.doFinal(datas, offSet, datas.length-offSet); } out.write(buff, 0, buff.length); i++; offSet = i * maxBlock; } }catch(Exception e){ throw new RuntimeException("加解密阀值为["+maxBlock+"]的数据时发生异常", e); } byte[] resultDatas = out.toByteArray(); IOUtils.closeQuietly(out); return resultDatas; } public static String encryptBASE64(byte[] key) throws Exception { // return (new BASE64Encoder()).encodeBuffer(key); return (Base64.encodeBase64String(key)); } public static byte[] decryptBASE64(String key) throws Exception { // return (new BASE64Decoder()).decodeBuffer(key); return (Base64.decodeBase64(key)); } }
------------------
扩展 AESUtil
package com.zhetang.netty; import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.security.SecureRandom; public class AESUtil { // AES secretKey length (must be 16 bytes) public static final String secretKey = "QAZWSXEDCRFVTGBH"; // AES密码器 private static Cipher cipher; // 字符串编码 private static final String KEY_CHARSET = "UTF-8"; // 算法方式 private static final String KEY_ALGORITHM = "AES"; // 算法/模式/填充 private static final String CIPHER_ALGORITHM_CBC = "AES/CBC/PKCS5Padding"; // 私钥大小128/192/256(bits)位 即:16/24/32bytes,暂时使用128,如果扩大需要更换java/jre里面的jar包 private static final Integer PRIVATE_KEY_SIZE_BIT = 128; private static final Integer PRIVATE_KEY_SIZE_BYTE = 16; /** * @param plainText 明文:要加密的内容 * @return 密文:加密后的内容,如有异常返回空串:"" * @Description: 加密 * @Author:杨攀 * @Since: 2019年9月17日上午10:17:18 */ public static String encrypt(String plainText) { return encrypt(secretKey, plainText); } /** * @param secretKey 密钥:加密的规则 16位 * @param plainText 明文:要加密的内容 * @return cipherText 密文:加密后的内容,如有异常返回空串:"" * @Description: 加密 * @Author:杨攀 * @Since: 2019年9月12日下午7:09:31 */ public static String encrypt(String secretKey, String plainText) { if (secretKey.length() != PRIVATE_KEY_SIZE_BYTE) { throw new RuntimeException("AESUtil:Invalid AES secretKey length (must be 16 bytes)"); } // 密文字符串 String cipherText = ""; try { // 加密模式初始化参数 initParam(secretKey, Cipher.ENCRYPT_MODE); // 获取加密内容的字节数组 byte[] bytePlainText = plainText.getBytes(KEY_CHARSET); // 执行加密 byte[] byteCipherText = cipher.doFinal(bytePlainText); cipherText = Base64.encodeBase64String(byteCipherText); } catch (Exception e) { throw new RuntimeException("AESUtil:encrypt fail!", e); } return cipherText; } /** * @param cipherText 密文:加密后的内容,即需要解密的内容 * @return 明文:解密后的内容即加密前的内容,如有异常返回空串:"" * @Description: 解密 * @Author:杨攀 * @Since: 2019年9月17日上午10:18:19 */ public static String decrypt(String cipherText) { return decrypt(secretKey, cipherText); } /** * @param secretKey 密钥:加密的规则 16位 * @param cipherText 密文:加密后的内容,即需要解密的内容 * @return * @Description: 解密 * @Author:杨攀 * @Since: 2019年9月12日下午7:10:06 */ public static String decrypt(String secretKey, String cipherText) { if (secretKey.length() != PRIVATE_KEY_SIZE_BYTE) { throw new RuntimeException("AESUtil:Invalid AES secretKey length (must be 16 bytes)"); } // 明文字符串 String plainText = ""; try { initParam(secretKey, Cipher.DECRYPT_MODE); // 将加密并编码后的内容解码成字节数组 byte[] byteCipherText = Base64.decodeBase64(cipherText); // 解密 byte[] bytePlainText = cipher.doFinal(byteCipherText); plainText = new String(bytePlainText, KEY_CHARSET); } catch (Exception e) { throw new RuntimeException("AESUtil:decrypt fail!", e); } return plainText; } /** * 初始化参数 * * @param secretKey 密钥:加密的规则 16位 * @param mode 加密模式:加密or解密 */ public static void initParam(String secretKey, int mode) { try { // 防止Linux下生成随机key SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); secureRandom.setSeed(secretKey.getBytes()); // 获取key生成器 KeyGenerator keygen = KeyGenerator.getInstance(KEY_ALGORITHM); keygen.init(PRIVATE_KEY_SIZE_BIT, secureRandom); // 获得原始对称密钥的字节数组 byte[] raw = secretKey.getBytes(); // 根据字节数组生成AES内部密钥 SecretKeySpec key = new SecretKeySpec(raw, KEY_ALGORITHM); // 根据指定算法"AES/CBC/PKCS5Padding"实例化密码器 cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC); IvParameterSpec iv = new IvParameterSpec(secretKey.getBytes()); cipher.init(mode, key, iv); } catch (Exception e) { throw new RuntimeException("AESUtil:initParam fail!", e); } } public static void main(String[] args) { long s = System.currentTimeMillis(); String text = "xxxx"; String encryptMsg = encrypt(secretKey, text); System.out.println("密文为:" + encryptMsg); long e = System.currentTimeMillis(); System.out.println(e - s); String decryptMsg = decrypt(secretKey, encryptMsg); System.out.println("明文为:" + decryptMsg); long d = System.currentTimeMillis(); System.out.println(d - e); } }
//超时处理
package com.zhetang.netty; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.timeout.IdleStateHandler; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; /** * Created with IntelliJ IDEA. * User:wq * Date:2021/4/22 * Time: 17:27 * Description: No Description */ @Component public class AlarmClient { @Scheduled(cron = "0/5 * * * * ?") public static void init()throws Exception{ NioEventLoopGroup eventExecutors = new NioEventLoopGroup(); try { //创建bootstrap对象,配置参数 Bootstrap bootstrap = new Bootstrap(); /** * ******************************************************************* * 如果不设置超时,连接会一直占用本地线程,端口,连接客户端一多,会导致本地端口用尽及CPU压力 */ bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000); //设置线程组 bootstrap.group(eventExecutors) //设置客户端的通道实现类型 .channel(NioSocketChannel.class) //使用匿名内部类初始化通道 .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //添加客户端通道的处理器 ch.pipeline().addLast("idleStateHandler",new IdleStateHandler(30,30,0)); ch.pipeline().addLast(new AlarmClientHandler()); } }); System.out.println("客户端准备就绪,随时可以起飞~"); //连接服务端 ChannelFuture channelFuture = bootstrap.connect("117.60.146.47", 10001).sync(); //对通道关闭进行监听 channelFuture.channel().closeFuture().sync(); } finally { //关闭线程组 eventExecutors.shutdownGracefully(); } } public static void main(String[] args) throws Exception { NioEventLoopGroup eventExecutors = new NioEventLoopGroup(); try { //创建bootstrap对象,配置参数 Bootstrap bootstrap = new Bootstrap(); //设置线程组 bootstrap.group(eventExecutors) //设置客户端的通道实现类型 .channel(NioSocketChannel.class) //使用匿名内部类初始化通道 .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //添加客户端通道的处理器 ch.pipeline().addLast(new AlarmClientHandler()); } }); System.out.println("客户端准备就绪,随时可以起飞~"); //连接服务端 ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8082).sync(); //对通道关闭进行监听 channelFuture.channel().closeFuture().sync(); } finally { //关闭线程组 eventExecutors.shutdownGracefully(); } } }
//handler 园区->市平台
package com.zhetang.netty; import com.alibaba.fastjson.JSON; import com.zhetang.influxdb.utils.InfluxDBUtil; import com.zhetang.mapper.mysqlMapper.AlarmHisTimeMapper; import com.zhetang.mapper.mysqlMapper.AlarmRealTimeMapper; import com.zhetang.mapper.mysqlMapper.PointOpcDataMapper; import com.zhetang.mapper.mysqlMapper.QysjProdBaseUserMapper; import com.zhetang.model.dto.city.CityAlarmDTO; import com.zhetang.model.dto.city.CityAlarmDataDTO; import com.zhetang.model.mysql.zw.AlarmHisTime; import com.zhetang.model.mysql.zw.AlarmRealTime; import com.zhetang.model.mysql.zw.PointOpcData; import com.zhetang.model.mysql.zw.QysjProdBaseUser; import com.zhetang.model.vo.city.CityRealTimeVO; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.util.CharsetUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import tk.mybatis.mapper.entity.Example; import javax.annotation.PostConstruct; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.ScheduledExecutorService; import java.util.stream.Collectors; /** * Created with IntelliJ IDEA. * User:wq * Date:2021/7/13 * Time: 15:34 * Description: 园区->市平台 报警数据 alarm_his_time(当前根据时间筛选) alarm_real_time(全查) */ @Component @Slf4j public class AlarmClientHandler extends SimpleChannelInboundHandler<ByteBuf> { private ScheduledExecutorService scheduledExecutorService; @Autowired private InfluxDBUtil influxDBUtil; @Autowired private AlarmRealTimeMapper alarmRealTimeMapper; @Autowired PointOpcDataMapper pointOpcDataMapper; @Autowired private AlarmHisTimeMapper alarmHisTimeMapper; @Autowired QysjProdBaseUserMapper qysjProdBaseUserMapper; @Value("${city.company.id}") private String cityCompanyId; @Value("${city.company.gateway.id}") private String cityCompanyGateWayId; private static AlarmClientHandler alarmClientHandler; private static String aseKey ="QAZWSXEDCRFVTGBH"; private static String appId ="570baedcda1111e9a46cd4ae52635598"; private static String alarmServiceId ="WARN_DATA"; //明盛企业编码 //private static String MSENTERPRISECODE = "320710067"; //网关编码 //private static String MSGATEWAY = "32071006701"; private static String reportType ="report"; //qysj_prod_user_id ms //private static String MS ="江苏明盛化工有限公司"; private static String HIGHALARMLEVEL="高"; private static String LOWALARMLEVEL ="低"; private static String unAlarm = "normal:alarm"; long initialDelay = 1; long period = 1; private long realtime_timeInterval = 1000 * 60 * 5; private long warn_timeInterval = 1000; @PostConstruct public void init() { alarmClientHandler = this; alarmClientHandler.influxDBUtil = this.influxDBUtil; alarmClientHandler.pointOpcDataMapper = this.pointOpcDataMapper; alarmClientHandler.alarmRealTimeMapper =this.alarmRealTimeMapper; alarmClientHandler.alarmHisTimeMapper= this.alarmHisTimeMapper; alarmClientHandler.qysjProdBaseUserMapper = this.qysjProdBaseUserMapper; alarmClientHandler.cityCompanyId = this.cityCompanyId; alarmClientHandler.cityCompanyGateWayId = this.cityCompanyGateWayId; } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { AlarmRealTimeMapper alarmRealTimeMapper = alarmClientHandler.alarmRealTimeMapper; InfluxDBUtil influxDBUtil = alarmClientHandler.influxDBUtil; AlarmHisTimeMapper alarmHisTimeMapper = alarmClientHandler.alarmHisTimeMapper; PointOpcDataMapper pointOpcDataMapper = alarmClientHandler.pointOpcDataMapper; QysjProdBaseUserMapper qysjProdBaseUserMapper = alarmClientHandler.qysjProdBaseUserMapper; String cityCompanyId = alarmClientHandler.cityCompanyId; String cityCompanyGateWayId = alarmClientHandler.cityCompanyGateWayId; String cityCompanyName = ""; CityAlarmDTO cityAlarmDTO = new CityAlarmDTO(); Example example1 = new Example(QysjProdBaseUser.class); example1.createCriteria().andEqualTo("cityEnterpriseCode",cityCompanyId); List<QysjProdBaseUser> qysjProdBaseUsers = qysjProdBaseUserMapper.selectByExample(example1); if(CollectionUtils.isNotEmpty(qysjProdBaseUsers)){ cityCompanyName = qysjProdBaseUsers.get(0).getName(); } List<CityAlarmDataDTO> cityAlarmDataDTOList = new ArrayList<>(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); Example example = new Example(AlarmHisTime.class); example.createCriteria().andEqualTo("responsibleUnit", cityCompanyName); //报警数据 List<AlarmRealTime> alarmRealTimes = alarmRealTimeMapper.selectByExample(example); //实时插入超上限报警,超下限报警 List<CityAlarmDataDTO> overAlarmDataDTOList = setRealTimeValue(alarmRealTimes, cityAlarmDataDTOList); //实时插入消警数据 List<CityAlarmDataDTO> allAlarmDataList = cancleAlarm(alarmRealTimes, overAlarmDataDTOList,cityCompanyName); cityAlarmDTO.setDataId(UUID.randomUUID().toString().replaceAll("-","")); cityAlarmDTO.setEnterpriseId(cityCompanyId); cityAlarmDTO.setGatewayId(cityCompanyGateWayId); cityAlarmDTO.setCollectTime(sdf.format(new Date())); cityAlarmDTO.setIsConnectDataSource(true); cityAlarmDTO.setReportType(reportType); //插入报警数据集合 cityAlarmDTO.setAlarms(allAlarmDataList); //市平台中间数据 String jsonString = JSON.toJSONString(cityAlarmDTO); try{ //封装市平台返回数据 String encrypt = AESpkcs7paddingUtil.encrypt(jsonString, aseKey); CityRealTimeVO cityRealTimeVO = new CityRealTimeVO(); cityRealTimeVO.setAppId(appId); cityRealTimeVO.setDataId(cityAlarmDTO.getDataId()); cityRealTimeVO.setServiceId(alarmServiceId); cityRealTimeVO.setData(encrypt); String returnJson = JSON.toJSONString(cityRealTimeVO); log.info(cityAlarmDTO.toString()); System.out.println(returnJson); if(ObjectUtils.allNotNull(cityAlarmDTO.getAlarms(),cityAlarmDTO.getEnterpriseId(),cityAlarmDTO.getGatewayId())){ ctx.writeAndFlush(Unpooled.copiedBuffer(returnJson+"@@", CharsetUtil.UTF_8)); } } catch (Exception e){ e.printStackTrace(); ctx.close(); } } /** * 封装市平台中间返回值 * @param alarmRealTimes * @param cityAlarmDataDTOList */ List<CityAlarmDataDTO> setRealTimeValue(List<AlarmRealTime> alarmRealTimes, List<CityAlarmDataDTO> cityAlarmDataDTOList){ AlarmRealTimeMapper alarmRealTimeMapper = alarmClientHandler.alarmRealTimeMapper; InfluxDBUtil influxDBUtil = alarmClientHandler.influxDBUtil; AlarmHisTimeMapper alarmHisTimeMapper = alarmClientHandler.alarmHisTimeMapper; PointOpcDataMapper pointOpcDataMapper = alarmClientHandler.pointOpcDataMapper; QysjProdBaseUserMapper qysjProdBaseUserMapper = alarmClientHandler.qysjProdBaseUserMapper; SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); if(!CollectionUtils.isEmpty(alarmRealTimes)){ alarmRealTimes.stream().filter(p->p != null).forEach(p->{ Optional<AlarmRealTime> first = alarmRealTimeMapper.listAlarmRealByUnique(p.getUnique()).stream().filter(m -> ObjectUtils.allNotNull(m)).findFirst(); AlarmRealTime alarmRealTime = first.isPresent() ? first.get() : null; Optional.ofNullable(alarmRealTime).ifPresent(s->{ PointOpcData pointOpcData = pointOpcDataMapper.selectBySensorAndAlarmOn(s.getUnique()); if(ObjectUtils.allNotNull(pointOpcData) && ObjectUtils.allNotNull(pointOpcData.getCityQuotaId())){ CityAlarmDataDTO cityAlarmDataDTO = new CityAlarmDataDTO(); Date startTime = p.getStartTime(); cityAlarmDataDTO.setAlarmTime(sdf.format(startTime)); cityAlarmDataDTO.setQuotaId(pointOpcData.getCityQuotaId()); Map map = influxDBUtil.selectInfkyxdb(s.getUnique()); cityAlarmDataDTO.setValue(Float.parseFloat(map.get("value").toString())); //报警类型 String alarmType = getAlarmType(p.getAlarmLevel()); cityAlarmDataDTO.setAlarmType(alarmType); //报警阈值 String thresholdRage = getThresholdRage(pointOpcData); String[] thresholdArray = thresholdRage.split(","); if(thresholdArray.length>1){ if(p.getAlarmLevel().contains(HIGHALARMLEVEL)){ cityAlarmDataDTO.setThreshold(Float.parseFloat(thresholdArray[1])); } if(p.getAlarmLevel().contains(LOWALARMLEVEL)){ cityAlarmDataDTO.setThreshold(Float.parseFloat(thresholdArray[0])); } } if(thresholdArray.length==1){ cityAlarmDataDTO.setThreshold(Float.parseFloat(thresholdArray[0])); } cityAlarmDataDTOList.add(cityAlarmDataDTO); } }); }); } return cityAlarmDataDTOList; } /** * 设置histime value * @param alarmHisTimes * @param cityAlarmDataDTOList * @return */ List<CityAlarmDataDTO> setHisTimeValue(List<AlarmHisTime> alarmHisTimes, List<CityAlarmDataDTO> cityAlarmDataDTOList){ AlarmRealTimeMapper alarmRealTimeMapper = alarmClientHandler.alarmRealTimeMapper; InfluxDBUtil influxDBUtil = alarmClientHandler.influxDBUtil; AlarmHisTimeMapper alarmHisTimeMapper = alarmClientHandler.alarmHisTimeMapper; PointOpcDataMapper pointOpcDataMapper = alarmClientHandler.pointOpcDataMapper; QysjProdBaseUserMapper qysjProdBaseUserMapper = alarmClientHandler.qysjProdBaseUserMapper; SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); if(!CollectionUtils.isEmpty(alarmHisTimes)){ alarmHisTimes.stream().filter(p->p != null).forEach(p->{ Optional<AlarmHisTime> first = alarmHisTimeMapper.listAlarmHisByUnique(p.getUnique()).stream().filter(m -> ObjectUtils.allNotNull(m)).findFirst(); AlarmHisTime alarmHisTime = first.isPresent() ? first.get() : null; Optional.ofNullable(alarmHisTime).ifPresent(s->{ PointOpcData pointOpcData = pointOpcDataMapper.selectBySensorAndAlarmOn(s.getUnique()); if(ObjectUtils.allNotNull(pointOpcData,pointOpcData.getCityQuotaId())){ CityAlarmDataDTO cityAlarmDataDTO = new CityAlarmDataDTO(); Date startTime = p.getStartTime(); cityAlarmDataDTO.setAlarmTime(sdf.format(startTime)); cityAlarmDataDTO.setQuotaId(pointOpcData.getCityQuotaId()); Map map = influxDBUtil.selectInfkyxdb(s.getUnique()); cityAlarmDataDTO.setValue(Float.parseFloat(map.get("value").toString())); //报警类型 //String alarmType = getAlarmType(p.getAlarmLevel()); cityAlarmDataDTO.setAlarmType(unAlarm); //报警阈值 String thresholdRage = getThresholdRage(pointOpcData); String[] thresholdArray = thresholdRage.split(","); if(thresholdArray.length>1){ if(p.getAlarmLevel().contains(HIGHALARMLEVEL)){ cityAlarmDataDTO.setThreshold(Float.parseFloat(thresholdArray[1])); } if(p.getAlarmLevel().contains(LOWALARMLEVEL)){ cityAlarmDataDTO.setThreshold(Float.parseFloat(thresholdArray[0])); } } if(thresholdArray.length==1){ cityAlarmDataDTO.setThreshold(Float.parseFloat(thresholdArray[0])); } cityAlarmDataDTOList.add(cityAlarmDataDTO); } }); }); } return cityAlarmDataDTOList; } /** * 获取消警数据 * @param cityAlarmDataDTOList * @return */ List<CityAlarmDataDTO> cancleAlarm( List<AlarmRealTime> alarmRealTimes, List<CityAlarmDataDTO> cityAlarmDataDTOList,String cityCompanyName){ AlarmRealTimeMapper alarmRealTimeMapper = alarmClientHandler.alarmRealTimeMapper; InfluxDBUtil influxDBUtil = alarmClientHandler.influxDBUtil; AlarmHisTimeMapper alarmHisTimeMapper = alarmClientHandler.alarmHisTimeMapper; PointOpcDataMapper pointOpcDataMapper = alarmClientHandler.pointOpcDataMapper; QysjProdBaseUserMapper qysjProdBaseUserMapper = alarmClientHandler.qysjProdBaseUserMapper; Date date = new Date(); List<AlarmHisTime> cancleAlarmList = null; SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd"); String formatDate = sdf.format(date); List<AlarmHisTime> alarmHisTimes = alarmHisTimeMapper.listAlarmHisByCreatedTime(formatDate, cityCompanyName); if(! CollectionUtils.isEmpty(alarmHisTimes)){ //获取当日消警数据,且此消警数据已经不再报警 cancleAlarmList = alarmHisTimes.stream().filter(p -> ObjectUtils.allNotNull(p.getUnique(), p.getGmtCreatedOn())) .map(p -> { List<String> RealTimeList = alarmRealTimes.stream().map(m -> m.getUnique()) .filter(d -> !p.getUnique().equals(d)).collect(Collectors.toList()); if (RealTimeList != null && RealTimeList.size() > 0) { return p; } if(alarmHisTimes == null ||RealTimeList.size() <=0){ return p; } return null; }).collect(Collectors.toList()); } List<CityAlarmDataDTO> cityAlarmDataDTOList1 = setHisTimeValue(cancleAlarmList, cityAlarmDataDTOList); return cityAlarmDataDTOList1; } /** * 报警类型 * @param alarmLevel * @return */ String getAlarmType(String alarmLevel){ switch (alarmLevel){ case "高限报警": return "alarmhi:alarm"; case "低限报警": return "alarmlo:alarm"; default: return null; } } /** * 报警阈值区间 * @param pointOpcDataVO * @return */ String getThresholdRage(PointOpcData pointOpcDataVO){ String zc = null; if(ObjectUtils.allNotNull(pointOpcDataVO)){ if(pointOpcDataVO.getFour()!=null && !"".equals(pointOpcDataVO.getFour())){ zc = pointOpcDataVO.getFour() ; } if(pointOpcDataVO.getFive()!=null && !"".equals(pointOpcDataVO.getFive())){ if("".equals(zc)){ zc =pointOpcDataVO.getFive() ; }else{ zc = zc +","+pointOpcDataVO.getFive() ; } } } return zc; } @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { log.info("Client received: " + msg.toString(CharsetUtil.UTF_8)); ctx.close(); log.info("当前通道已关闭!!!"); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { log.info("client 异常!!!!"); cause.printStackTrace(); ctx.close(); } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { log.info("client 连接超时被捕获 !!!!"); ctx.close(); // super.userEventTriggered(ctx, evt); } public String getXmlPublicKey() { // ras公钥 String rasPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCB0vo8UhGB5uGkZlcupo+NmcAg8jz4Th+CmLtBKp4EBFof3io1LBXTzaQ7KIFnvhJRQahbm/IZInibBrHQbmQzAoK9417fAGFBeZ1Zb4O9pfb5Nsu5cXsyD/pgJJ8IW4xuIrPSMXCU5jnQJjyAKRnPoASY4UPi4k60PYT4JvFdlQIDAQAB"; //DES密钥 (8字节) String desKey = "wQNC2380"; //DES加密数据 //RSA加密key RSAPublicKey publicKey = null; try { publicKey = RSAUtil.getPublicKey(rasPublicKey); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeySpecException e) { e.printStackTrace(); } String xmlPublicKey = RSAUtil.publicEncrypt(desKey, publicKey); return xmlPublicKey; } }
netty设置超时链接:
//客户端超时链接
bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000);
//添加
服务端添加IdleStateHandler心跳检测处理器,并添加自定义处理Handler类实现userEventTriggered()方法作为超时事件的逻辑处理;
设定IdleStateHandler心跳检测每五秒进行一次读检测,如果五秒内ChannelRead()方法未被调用则触发一次userEventTrigger()方法
pipeline.addLast(
new
IdleStateHandler(61, 30, 0, TimeUnit.SECONDS));
public class Client4 { public static void main(String[] args) { //worker负责读写数据 EventLoopGroup worker = new NioEventLoopGroup(); long st = System.currentTimeMillis(); try { //辅助启动类 Bootstrap bootstrap = new Bootstrap(); //设置线程池 bootstrap.group(worker); //设置socket工厂 bootstrap.channel(NioSocketChannel.class); /** * ******************************************************************* * 如果不设置超时,连接会一直占用本地线程,端口,连接客户端一多,会导致本地端口用尽及CPU压力 */ bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000); //设置管道 bootstrap.handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { //获取管道 ChannelPipeline pipeline = socketChannel.pipeline(); pipeline.addLast(new LengthFieldBasedFrameDecoder(10000, 0, 4, 0, 4)); pipeline.addLast(new ProtobufDecoder(MyBaseProto.BaseProto.getDefaultInstance())); pipeline.addLast(new LengthFieldPrepender(4)); pipeline.addLast(new ProtobufEncoder()); pipeline.addLast(new IdleStateHandler(61, 30, 0, TimeUnit.SECONDS)); pipeline.addLast(new ClientHeartbeatHandler()); //处理类 pipeline.addLast(new ClientHandler4Heart()); } }); //发起异步连接操作(
hander 里面添加
@Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { log.info("client 连接超时被捕获 !!!!"); ctx.close(); // super.userEventTriggered(ctx, evt); }
https://blog.csdn.net/u013967175/article/details/78591810
Netty(六)UDP在netty中的使用
关于UDP的介绍,这里不在阐述。
相比于TCP而言,UDP不存在客户端和服务端的实际链接,因此不需要为连接(ChannelPipeline)设置handler。
服务端:
1 public void run(int port)throws Exception{ 2 EventLoopGroup group = new NioEventLoopGroup(); 3 try { 4 Bootstrap b = new Bootstrap(); 5 b.group(group).channel(NioDatagramChannel.class) 6 .option(ChannelOption.SO_BROADCAST,true) 7 .handler(new UdpServerHandler()); 8 9 b.bind(port).sync().channel().closeFuture().await(); 10 } 11 finally { 12 group.shutdownGracefully(); 13 } 14 }
1 @Override 2 public void messageReceived(ChannelHandlerContext channelHandlerContext, 3 DatagramPacket datagramPacket) throws Exception { 4 // 因为Netty对UDP进行了封装,所以接收到的是DatagramPacket对象。 5 String req = datagramPacket.content().toString(CharsetUtil.UTF_8); 6 System.out.println(req); 7 8 if("啪啪啪来拉!!!".equals(req)){ 9 channelHandlerContext.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer( 10 "结果:",CharsetUtil.UTF_8),datagramPacket.sender())); 11 } 12 }
客户端:
public void run(int port)throws Exception{ EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group).channel(NioDatagramChannel.class) .option(ChannelOption.SO_BROADCAST,true) .handler(new UdpClientHandler()); Channel ch = b.bind(0).sync().channel(); // 向网段类所有机器广播发UDP ch.writeAndFlush( new DatagramPacket( Unpooled.copiedBuffer("啪啪啪来拉!!!", CharsetUtil.UTF_8), new InetSocketAddress( "255.255.255.255",port ))).sync(); if(!ch.closeFuture().await(15000)){ System.out.println("查询超时!!!"); } } finally { group.shutdownGracefully(); } }
public void messageReceived(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket) throws Exception { String response = datagramPacket.content().toString(CharsetUtil.UTF_8); if(response.startsWith("结果:")){ System.out.println(response); channelHandlerContext.close(); } }
源码下载
源码在src/main/java/Unp下,分为客户端和服务端,他们的代码基本和Netty入门章节的代码类似,只是减少了相关的解码器使用。
GitHub地址:https://github.com/orange1438/Netty_Course
关于netty的多个handler链式模式
1. 老规矩, 引入我们喜闻乐见的maven依赖 <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.6.Final</version> </dependency> 服务端 2.1: 服务端引导类: public class EchoServer { private int port; private EchoServer(int port) { this.port = port; } private void start() throws Exception { System.out.println("Echo Server Start"); EventLoopGroup group = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(group) .channel(NioServerSocketChannel.class) .localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoOutboundHandler1()); ch.pipeline().addLast(new EchoOutboundHandler2()); ch.pipeline().addLast(new EchoInboundHandler1()); ch.pipeline().addLast(new EchoInboundHandler2()); } }); ChannelFuture f = b.bind().sync(); System.out.println("Server Start Listen At: " + port); f.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new EchoServer(port).start(); } } 2.2 EchoOutboundHandler1 public class EchoInboundHandler1 extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { // 读取msg中的数据 ByteBuf result = (ByteBuf) msg; byte[] bytes = new byte[result.readableBytes()]; result.readBytes(bytes); String resultStr = new String(bytes); System.out.println("Server Received: " + resultStr + ": Inbound 1 Is OK"); // 处理完msg中的数据后往msg中重新存放新的数据继续传递 result.writeBytes(resultStr.getBytes()); ctx.fireChannelRead(result); } } 2.3 EchoInboundHandler2 public class EchoInboundHandler2 extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { // 读取msg中的数据 ByteBuf result = (ByteBuf) msg; byte[] bytes = new byte[result.readableBytes()]; result.readBytes(bytes); String resultStr = new String(bytes); System.out.println("Server Received: " + resultStr + ": Inbound 2 Is OK"); // 处理完msg中的数据后往msg中重新存放新的数据继续传递 result.writeBytes(resultStr.getBytes()); ctx.write(result); } } 2.4 EchoOutboundHandler2 public class EchoOutboundHandler2 extends ChannelOutboundHandlerAdapter { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { // 读取msg中的数据 ByteBuf result = (ByteBuf) msg; byte[] bytes = new byte[result.readableBytes()]; result.readBytes(bytes); String resultStr = new String(bytes); System.out.println("Server Received: " + resultStr + ": Outbound 2 Is OK"); // 处理完msg中的数据后往msg中重新存放新的数据继续传递 result.writeBytes(resultStr.getBytes()); ctx.write(result); } } 2.5 EchoOutboundHandler1 public class EchoOutboundHandler1 extends ChannelOutboundHandlerAdapter { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { // 读取msg中的数据 ByteBuf result = (ByteBuf) msg; byte[] bytes = new byte[result.readableBytes()]; result.readBytes(bytes); String resultStr = new String(bytes); System.out.println("Server Received: " + resultStr + ": Outbound 1 Is OK"); // 处理完msg中的数据后往msg中重新存放新的数据继续传递 result.writeBytes(resultStr.getBytes()); ctx.write(result); ctx.flush(); } } 客户端 public class EchoClient { private String host; private int port; private EchoClient(String host, int port) { this.host = host; this.port = port; } private void start() throws Exception { System.out.println("Echo Client Start"); EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .remoteAddress(new InetSocketAddress(host, port)) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoClientHandler()); } }); ChannelFuture f = b.connect().sync(); System.out.println("Server Client Listen IP: [" + host + ":" + port + "]"); f.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } public static void main(String[] args) throws Exception { String host = "127.0.0.1"; int port = 8080; int len = 2; if (args.length == len) { host = args[0]; port = Integer.parseInt(args[1]); } new EchoClient(host, port).start(); } } public class EchoClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) { ctx.writeAndFlush(Unpooled.copiedBuffer("Netty Rocks!", CharsetUtil.UTF_8)); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { // 读取msg中的数据 ByteBuf result = (ByteBuf) msg; byte[] bytes = new byte[result.readableBytes()]; result.readBytes(bytes); String resultStr = new String(bytes); System.out.println("Echo Client Received Is OK: " + resultStr); ctx.close(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } 结果: 服务端: 客户端: 注意事项: 1. ChannelInboundHandler之间的传递, 通过调用 ctx.fireChannelRead(msg) 实现; 调用ctx.write(msg) 将传递到ChannelOutboundHandler 2. ctx.write()方法执行后, 需要调用flush()方法才能令它立即执行 3. ChannelOutboundHandler 在注册的时候需要放在最后一个ChannelInboundHandler之前, 否则将无法传递到ChannelOutboundHandler
https://blog.csdn.net/weixin_34008784/article/details/94512231
111