主要项目框架采用的事若依的框架,就不做多介绍
下面主要贴代码和部分注释
在pom.xml文件中引入netty包
<!--netty--><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.53.Final</version></dependency>
2、编写NettyServer类
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 org.springframework.stereotype.Component;/*** @Author DCXPC* @Description //TODO 采用netty 监听服务器端口,并处理后面逻辑* @Date 2023/9/15 9:57**/
@Component
public class NettyServer {private final int port = 9007;public void start() throws InterruptedException {EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup, workerGroup)// 指定Channel.channel(NioServerSocketChannel.class)//使用自定义处理类.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();// 添加自定义的ChannelHandlerpipeline.addLast(new MyChannelHandler());}})//服务端可连接队列数,对应TCP/IP协议listen函数中backlog参数.option(ChannelOption.SO_BACKLOG, 128)//保持长连接,2小时无数据激活心跳机制.childOption(ChannelOption.SO_KEEPALIVE, true);// 绑定端口,开始接收进来的连接ChannelFuture channelFuture = serverBootstrap.bind(port).sync();channelFuture.channel().closeFuture().sync();} finally {workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}
}
3、编写自定义处理类MyChannelHandler
package com.ruoyi.common.netty;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;import java.text.SimpleDateFormat;
import java.util.Date;/*** @author DCXPC* @ClassName MyChannelHandler* @description: TODO 自定义的数据处理方法,用于处理收到的数据* @date 2023年09月14日*/
public class MyChannelHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 处理接收到的数据ByteBuf byteBuf = (ByteBuf) msg;System.out.println("----------------------------------------------------------------------------------------------------");System.out.println("Received time: " +sdf.format(new Date()));/**数据转换**/// 获取字节数组byte[] bytes = new byte[byteBuf.readableBytes()];byteBuf.getBytes(byteBuf.readerIndex(), bytes);// 将字节数组转换为十六进制字符串StringBuilder hexString = new StringBuilder();for (byte b : bytes) {String hex = Integer.toHexString(b & 0xFF);if (hex.length() == 1) {hexString.append('0'); // 如果得到的十六进制只有一位,则在前面补零}hexString.append(hex);}String hexStringResult = hexString.toString(); // 转换后的十六进制字符串System.out.println("Received data:"+hexStringResult);dealData(hexStringResult);/**接收到的数据是水文规约,需要翻译成有用的数据*/
// dealData(
// "7e7e" +//4
// "01" +//6
// "0034120201" +//16
// "1234" +//20
// "32" +//22
// "003b" +//26
// "02" +//28
// "0102" +//32
// "230914203800" +//44
// "f1f1" +//48
// "0034120201" +//58
// "49" +//60
// "f0f0" +//64
// "2309142038" +//74
// "3c23" +//水位引导 78
// "00002321" +//水位2.321 86
// "682a" +//表1瞬时流量引导 90
// "0000004644" +//表1瞬时流量46.44 100
// "6033" +//表1累积流量引导 104
// "000012369332" +//表1累积流量12369.332 116
// "692a" +//表2瞬时流量引导 120
// "0000008723" +//表2瞬时流量87.23 130
// "6133" +//表2累积流量引导 134
// "000023223654" +//表2累积流量23223.654 146
// "03ecaf");byteBuf.release();}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {// 处理异常cause.printStackTrace();ctx.close();}//处理数据public void dealData(String hexMsg){String date = hexMsg.substring(32,44);System.out.println("发报时间:"+date);String waterleve = hexMsg.substring(78,86);System.out.println("水位高度:"+addpoint(waterleve,hexMsg.substring(77,78)));;String ssll1 = hexMsg.substring(90,100);System.out.println("表1瞬时流量:"+addpoint(ssll1,"2"));;String ljll1 = hexMsg.substring(104,116);System.out.println("表1累积流量:"+addpoint(ljll1,"3"));;String ssll2 = hexMsg.substring(120,130);System.out.println("表2瞬时流量:"+addpoint(ssll2,"2"));;String ljll2 = hexMsg.substring(134,146);System.out.println("表2累积流量:"+addpoint(ljll2,"3"));;}//小数点添加public float addpoint(String numStr,String locationStr){int locationNum = Integer.valueOf(locationStr);StringBuilder sb = new StringBuilder(numStr);sb.insert(numStr.length()-locationNum,".");float num = Float.valueOf(sb.toString());return num;}}
4、在启动类上加上该启动配置
import com.ruoyi.common.netty.NettyServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;/*** 启动程序** @author ruoyi*/
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class RuoYiApplication implements CommandLineRunner {@Autowiredprivate NettyServer nettyServer;private static final Logger log = LoggerFactory.getLogger(RuoYiApplication.class);public static void main(String[] args) {SpringApplication.run(RuoYiApplication.class, args);System.out.println("---项目启动成功---");}@Overridepublic void run(String... args) throws Exception {nettyServer.start();}
}
5、后续有增加的功能时候,再进行更新
文章参考:https://blog.51cto.com/u_16099206/6430191
Java基础之《netty(12)—netty入门》_java netty tcp_csj50的博客-CSDN博客