Netty实战应用学习笔记-中级拓展篇(三)

bugstack虫洞栈 | netty4.1案例文章列表汇总,跟着案例学Netty itstack-demo-netty netty4.x案例 微信公众号:bugstack虫洞栈,欢迎您的关注&获取更多案例与源码!博客栈:https://bugstack.cn 本专题针对netty4.x分为从;基础入门篇(九篇)、中级拓展篇(八篇)、高级应用篇(三章),由浅入深实现netty服务功能,介绍netty如何从上手到实战。 基础入门篇(九篇) netty案例,netty4.1... 阅读详情

💡 项目三:Java对象传输(Protostuff)

项目概述

项目名称:itstack-demo-netty-2-03
核心功能:使用Protostuff直接传输Java对象,无需定义proto文件
技术要点:Protostuff序列化、自定义编解码器、Schema缓存

为什么需要这个项目?

实际问题:

  • Protobuf需要定义.proto文件,开发效率低
  • 每次修改数据结构都要重新编译
  • 只在Java系统内部通信,不需要跨语言
  • 希望直接使用POJO对象,简化开发

解决方案:

  • ✅ 无需定义.proto文件,直接使用Java Bean
  • ✅ 性能接近Protobuf,开发效率更高
  • ✅ 支持复杂的Java对象(嵌套、集合等)
  • ✅ 运行时动态生成Schema,灵活方便

适用场景:

  • Java微服务之间的RPC通信
  • 分布式系统内部数据传输
  • 需要传输复杂Java对象的场景
  • 快速开发原型系统

核心知识点

1. Protostuff vs Protobuf
特性ProtobufProtostuff
定义文件需要.proto文件不需要
编译需要protoc编译不需要
使用方式生成的Java类直接使用POJO
性能高高(相当)
跨语言支持仅Java
开发效率低高

选择建议:

  • Java系统内部通信 → Protostuff
  • 跨语言通信 → Protobuf
2. 定义POJO对象

MsgInfo.java

public class MsgInfo {
    private String channelId;
    private String msgContent;
    
    // 必须有无参构造函数!
    public MsgInfo() {
    }
    
    public MsgInfo(String channelId, String msgContent) {
        this.channelId = channelId;
        this.msgContent = msgContent;
    }
    
    // getter/setter...
}

关键点:

  • ✅ 普通的Java Bean
  • ✅ 无需继承任何类
  • ✅ 无需添加注解
  • ⚠️ 必须提供无参构造函数
3. 序列化工具类

SerializationUtil.java

public class SerializationUtil {
    // Schema缓存(避免重复创建)
    private static Map<Class<?>, Schema<?>> cachedSchema = 
        new ConcurrentHashMap<>();
    
    // Objenesis用于创建对象实例
    private static Objenesis objenesis = new ObjenesisStd();
    
    /**
     * 序列化:对象 → 字节数组
     */
    public static <T> byte[] serialize(T obj) {
        Class<T> cls = (Class<T>) obj.getClass();
        LinkedBuffer buffer = LinkedBuffer.allocate(
            LinkedBuffer.DEFAULT_BUFFER_SIZE
        );
        try {
            Schema<T> schema = getSchema(cls);
            return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
        } finally {
            buffer.clear();  // 清理缓冲区
        }
    }
    
    /**
     * 反序列化:字节数组 → 对象
     */
    public static <T> T deserialize(byte[] data, Class<T> cls) {
        T message = objenesis.newInstance(cls);  // 创建实例
        Schema<T> schema = getSchema(cls);
        ProtostuffIOUtil.mergeFrom(data, message, schema);
        return message;
    }
    
    /**
     * 获取Schema(带缓存)
     */
    private static <T> Schema<T> getSchema(Class<T> cls) {
        Schema<T> schema = (Schema<T>) cachedSchema.get(cls);
        if (schema == null) {
            schema = RuntimeSchema.createFrom(cls);  // 运行时创建
            cachedSchema.put(cls, schema);
        }
        return schema;
    }
}

核心概念:

  • Schema:描述对象结构的元数据(类似数据库表结构)
  • LinkedBuffer:临时缓冲区,使用后需清理
  • Objenesis:不调用构造函数创建对象
  • cachedSchema:缓存Schema,提升性能
4. 自定义编解码器

ObjEncoder.java

public class ObjEncoder extends MessageToByteEncoder {
    private Class<?> genericClass;
    
    public ObjEncoder(Class<?> genericClass) {
        this.genericClass = genericClass;
    }
    
    @Override
    protected void encode(ChannelHandlerContext ctx, Object in, ByteBuf out) {
        if (genericClass.isInstance(in)) {
            byte[] data = SerializationUtil.serialize(in);
            out.writeInt(data.length);  // 写入长度(4字节)
            out.writeBytes(data);       // 写入数据
        }
    }
}

ObjDecoder.java

public class ObjDecoder extends ByteToMessageDecoder {
    private Class<?> genericClass;
    
    public ObjDecoder(Class<?> genericClass) {
        this.genericClass = genericClass;
    }
    
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, 
                         List<Object> out) {
        // 1. 检查是否有足够的字节读取长度字段
        if (in.readableBytes() < 4) {
            return;  // 等待更多数据
        }
        
        // 2. 标记当前读位置
        in.markReaderIndex();
        
        // 3. 读取数据长度
        int dataLength = in.readInt();
        
        // 4. 检查是否有足够的数据
        if (in.readableBytes() < dataLength) {
            in.resetReaderIndex();  // 重置读位置
            return;  // 等待更多数据
        }
        
        // 5. 读取数据并反序列化
        byte[] data = new byte[dataLength];
        in.readBytes(data);
        out.add(SerializationUtil.deserialize(data, genericClass));
    }
}

解决粘包/半包的关键:

  • markReaderIndex():标记读位置
  • resetReaderIndex():重置到标记位置
  • 长度字段前缀:[4字节长度][N字节数据]
5. Pipeline配置

MyChannelInitializer.java

public class MyChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel channel) {
        // 对象传输处理
        channel.pipeline().addLast(new ObjDecoder(MsgInfo.class));
        channel.pipeline().addLast(new ObjEncoder(MsgInfo.class));
        channel.pipeline().addLast(new MyServerHandler());
    }
}

项目总结

优点:

  • ✅ 无需定义.proto文件
  • ✅ 直接使用POJO对象
  • ✅ 开发效率高
  • ✅ 性能接近Protobuf

缺点:

  • ❌ 仅支持Java
  • ❌ 需要提供无参构造函数

适用场景:

  • Java微服务之间的RPC通信
  • 分布式系统内部数据传输
  • 需要传输复杂Java对象的场景

netty案例,netty4.1中级拓展篇三《Netty传输Java对象》 前言介绍 Netty在实际应用级开发中,有时候某些特定场景下会需要使用Java对象类型进行传输,但是如果使用Java本身序列化进行传输,那么对性能的损耗比较大。为此我们需要借助protostuff-core的工具包将对象以二进制形式传输并做编码解码处理。与直接使用protobuf二进制传输方式不同,这里不需要定义proto文件,而是需要实现对象类型编码解码器,用以传输自定义Java对象。 pro... 阅读详情

相关推荐

netty案例,netty4.1中级拓展篇一《Netty与SpringBoot整合》

前言介绍 在实际的开发中,我们需要对netty服务进行更多的操作,包括;获取它的状态信息、启动/停止、对客户端用户强制下线等等,为此我们需要把netty服务加入到web系统中,那么本章节介绍如何将Netty与SpringBoot整合。 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使...

bugstack虫洞栈 2642

Netty实战应用学习笔记-中级拓展篇(一)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 1072

netty案例,netty4.1中级拓展篇五《基于Netty搭建WebSocket,模仿微信聊天页面》

前言介绍 本章节我们模仿微信聊天页面,开发一个基于Netty搭建WebSocket通信案例。Netty的应用方面非常广;聊天、MQ、RPC、数据等等,在5G到来的时候更加需要大量数据传输,Netty的应用也会更加广阔。 1、这个案例使用SpringBoot+Netty+WebSocket搭建功能。 2、使用Netty提供的HttpServerCodec、HttpObjectAggregator、...

bugstack虫洞栈 3072

Netty实战应用学习笔记-中级拓展篇(六)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 630

netty案例,netty4.1中级拓展篇七《Netty请求响应同步通信》

前言介绍 在我们实现开发RPC框架的时候,需要选择socket的通信方式。而我们知道一般情况下socket通信类似与qq聊天,发过去消息,什么时候回复都可以。但是我们RPC框架通信,从感觉上类似http调用,需要在一定时间内返回,否则就会发生超时断开。这里我们选择netty作为我们的socket框架,采用future方式进行通信。 Dubbo:国内最早开源的 RPC 框架,由阿里巴巴公司开发并于...

bugstack虫洞栈 2265

netty案例,netty4.1中级拓展篇二《Netty使用Protobuf传输数据》

前言介绍 在netty数据传输过程中可以有很多选择,比如;字符串、json、xml、java对象,但为了保证传输的数据具备;良好的通用性、方便的操作性和传输的高性能,我们可以选择protobuf作为我们的数据传输格式。目前protobuf可以支持;C++、C#、Dart、Go、Java、Python等,也可以在JS里使用。知识点;ProtobufDecoder、ProtobufEncoder、Pr...

bugstack虫洞栈 2080

Dapper 快速上手指南:30 秒把数据库查询映射成 C 对象

Dapper 是 .NET 里一款轻量级 ORM / 对象映射器,核心就一件事:用最少的代码,把数据库查询结果映射成 C# 对象。它扩展 ADO.NET 的 `IDbConnection` 接口,不生成额外代码、不改变你的 SQL 写法,装好就能用。这篇 Dapper 教程带你从安装、配置到跑通第一次查询,顺带避开最常见的几个坑。 [![Dapper .NET 轻量 ORM 数据库映射项目主图]

gitblog_00439的博客 401

netty案例,netty4.1中级拓展篇四《Netty传输文件、分片发送、断点续传》

前言介绍 1、在实际应用中我们经常使用到网盘服务,他们可以高效的上传下载较大文件。那么这些高性能文件传输服务,都需要实现的分片发送、断点续传功能。 2、在Java文件操作中有RandomAccessFile类,他可以支持文件的定位读取和写入,这样就满足了我们对文件分片的最基础需求。 3、Netty服务端启动后,可以向客户端发送文件传输指令;允许接收文件、控制读取位点、记录传输标记、文件接收完成。 ...

bugstack虫洞栈 3229

Netty实战应用学习笔记-中级拓展篇(十二)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 1087

netty案例,netty4.1中级拓展篇八《Netty心跳服务与断线重连》

前言介绍 在我们使用netty中,需要监测服务是否稳定以及在网络异常链接断开时候可以自动重连。需要实现监听;f.addListener(new MyChannelFutureListener()) 环境准备 1、jdk1.8【jdk1.7以下只能部分支持netty】 2、Netty4.1.36.Final【netty3.x 4.x 5每次的变化较大,接口类名也随着变化】 代码示例 itstack-...

bugstack虫洞栈 2069

netty案例,netty4.1中级拓展篇十二《Netty流量整形数据流速率控制分析与实战》

作者:付政委 | 关注微信公众号:bugstack虫洞栈,获取专题案例源码 前言介绍 你是否使用过某盘,在前几年我们使用的时候速度飞快,上传下载嗖嗖嗖。但是近年来只要不办会员,速度慢的像蜗牛,当然人家也得赚钱我们能理解。那么这样的限速是怎么实现的呢,我们这个案例使用Netty的流量整形进行限速传输,测试过程中当你把流量整形功能去掉后你就是年费VIP。 流量整形(Traffic Shaping...

bugstack虫洞栈 3696

Netty实战应用学习笔记-中级拓展篇(九)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 1063

智能座舱架构与芯片- (10) 音频篇 下

若将有限个 量化样值的绝对值从小到大依次排列,并对应地依次赋予一个十进制数字代码(例如,赋予样值0的十进制数字代码为0),在码前以“+”、“-”号为前缀,来 区分样值的正、负,则量化后的抽样信号就转化为按抽样时序排列的一串十进制数字码流,即十进制数字信号。如果声学密封不牢,来自内部结构的噪声可能到达传感器,两个传感器之间的泄漏可能降低BF算法的性能。未来,随着汽车电动化的普及,传统的ANC降噪所针对的发动机噪音已经不复存在,而路噪问题将越发明显,因此,全新的RNC主动路噪消减技术将会有一个更为宽广的市场。

joanna_xiao的博客 3847

Netty实战应用学习笔记-中级拓展篇(八)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 640

无法找到 Adobe PDF资源文件。“Acrobat PDFMaker“您必须具有”管理员”权限方可安装这些文件...错误怎么解决

本文的内容是无法找到 Adobe PDF资源文件。“Acrobat PDFMaker“您必须具有”管理员”权限方可安装这些文件...错误的解决办法。

西岸贤 1万+

用Python和sklearn预测NBA比赛胜负:从数据清洗到模型优化的完整流程

本文详细介绍了如何使用Python和sklearn构建NBA比赛胜负预测模型,涵盖从数据清洗、特征工程到模型优化与部署的完整流程。通过对比随机森林、XGBoost等主流算法,提供实战技巧和解决方案,帮助数据爱好者掌握体育数据分析的核心技术。

weixin_30823001的博客 135

Netty实战应用学习笔记-中级拓展篇(十三)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 570

【学习笔记】人群归因分数 PAF 以及combined PAF

人群归因风险比例(Population Attributable Fraction,PAF)是一个流行病学指标,它估计了在总体中,如果能消除一个特定的危险因素,能预防多少百分比的疾病或健康结果。简单来说,PAF回答的是:“如果没有这个风险因素,总体中会有多少病例是可以避免的?

weixin_53499537的博客 4905

Netty实战应用学习笔记-中级拓展篇(五)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 636

(入门向)在Ubuntu22.04.3安装Matlab2021b,以及无法安装在当前目录下的解决办法(见最后)

还有这个/usr/local是只读状态,我试过sudo chmod..去改那个文件的读,结果还是安装不了,我不是这个默认路径,因为它文件夹还是只读,于是我在matlab2021b下创了一个bin,并选上。输入完成后,依次按y,因为里面有三个文件,他会让你确定3次密码,直接yyy跳过即可。你可能会遇到装不下的情况,这个软件占30g,可是你分配给虚拟机就剩10g。,于是我去Downloads下建了一个matlab2021b文件夹,果然好使,3).此时,会提示你输入密码,因为这个rar是有密码的,

harrype的博客 7287

ESP32实战:破解校园网WPA2-Enterprise认证的完整指南

本文详细介绍了如何使用ESP32开发板破解校园网WPA2-Enterprise认证的完整指南。通过硬件准备、环境搭建、核心代码实现及常见问题排查,帮助开发者解决企业级WiFi连接难题,特别适用于校园网环境下的物联网设备开发。

weixin_29194817的博客 457

Netty实战应用学习笔记-中级拓展篇(七)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 322

Android面试指南及参考答案

【摘要】LesPark招聘Android开发工程师,要求3年以上经验,负责客户端功能开发与优化。岗位需掌握Java、多线程、网络编程(TCP/UDP/HTTP)及性能调试工具。面试重点考察:1)核心技术如网络协议选择(TCP可靠消息/UDP实时音视频)、内存泄漏分析;2)业务能力如图片懒加载三级缓存设计、启动速度优化案例;3)高阶系统原理如插件化框架设计;4)行为问题应对策略。建议候选人准备并发编程、JVM差异等深度知识,并量化项目优化成果,尤其关注社交应用相关的图片处理、实时通信等场景题。

郑伟强dev的专栏 806

Netty 4.1 使用 Protobuf 传输数据:itstack-demo-netty 中级拓展篇二实战解析

本篇技术指南以 CodeGuide 开源仓库中 itstack-demo-netty 中级拓展篇二的完整案例为蓝本,讲解如何在 Netty 4.1 服务端与客户端之间使用 Google Protocol Buffers(Protobuf)作为数据传输格式,涵盖 `MsgInfo.proto` 协议定义、protoc 编译、`ProtobufDecoder` / `ProtobufEncoder`

gitblog_00156的博客 248

大厂硬件机试选择题与判断题解析-卷1

本文精选30道硬件工程师机试题目,涵盖模拟电路、数字电路、PCB设计三大方向。模拟电路部分重点考察运算放大器、滤波器、整流电路等核心知识;数字电路部分聚焦计数器、电平转换等关键技术;PCB设计部分强调高速信号处理、阻抗控制等实践要点。题目均来自华为、小米等大厂真题,剔除基础题,每道题附详细解析,包括正确答案推导过程及相关公式说明。特别针对易错概念(如负反馈类型判断、Q值与带宽关系等)进行重点解析,帮助考生系统掌握硬件设计的核心考点和解题思路。

启芯硬件的博客 679

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

上一篇: Netty实战应用学习笔记-中级拓展篇(二)
下一篇: Netty实战应用学习笔记-中级拓展篇(四)
不早睡不改名@
博客等级 码龄5年 536粉丝 306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值