【七】Netty JBoss Marshallin 编解码

news2024/11/16 19:50:54

Netty JBoss Marshallin 编解码

  • 介绍
  • Marshallin 开发环境
    • maven 依赖
  • 业务场景模拟
    • 流程图
  • 代码展示
    • 订购采购消息 POJO 类
    • 订购应答消息 POJO 类
    • SubscribeReqServer 服务端启动类
    • MarshallingCodeCFactory
    • 服务端业务处理类 SubscribeServerHandler
    • 客户端启动类 SubscribeClient
    • 客户端 业务处理类 SubscribeClientHandler
    • 重点部分说明
  • 效果展示
    • 服务端打印
    • 客户端打印
  • 踩坑说明
    • 解决办法
  • 总结

介绍

JBoss Marshalling 是一个Java 对象序列化包,对JDK 默认的序列化框架进行了优化,但又保持跟java.io.Serializable 接口进行兼容(即POJO 类只要实现了Serializable接口,就支持编解码)。同时增加了一些可调的参数和附加的特性,可以通过工厂类进行配置。

Marshallin 开发环境

maven 依赖

由于我们只是用到了它的序列化类库,因此,只需要下载 jboss-marshlling-1.4.11.Final 和 jboss-marshalling-serial-1.4.11.Final 类库。采用 1.3.0 版本也行。

 		<dependency>
            <groupId>org.jboss.marshalling</groupId>
            <artifactId>jboss-marshalling</artifactId>
            <version>1.4.11.Final </version>
        </dependency>

        <dependency>
            <groupId>org.jboss.marshalling</groupId>
            <artifactId>jboss-marshalling-serial</artifactId>
            <version>1.4.11.Final </version>
        </dependency>

业务场景模拟

流程图

在这里插入图片描述
(1)Netty 服务端接收客户端的用户订购请求信息,消息定义如下
在这里插入图片描述

(2)服务端接收到请求消息,对用户名进行合法性校验,如果合法,则构造订购成功的应答消息给客户端,订购应答消息定义如下
在这里插入图片描述

代码展示

订购采购消息 POJO 类

public class SubscribeReq implements Serializable {
    private static final long serialVersionUID=1L;
    //订购编号
    private int subReqID;
    //用户名
    private String userName;
    //订购的产品名称
    private String productName;
    //订购者的电话号码
    private String phoneNumber;
    //订购者的家庭地址
    private String address;


    public int getSubReqID() {
        return subReqID;
    }

    public void setSubReqID(int subReqID) {
        this.subReqID = subReqID;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String toString(){
        return "SubscribeReq [ subReqID = "+subReqID+" , userName = " +
                ""+userName+" , productName = "+productName+" ," +
                " phoneNumber = "+phoneNumber+" , address = "+address+" ]";
    }
}

订购应答消息 POJO 类

public class SubscribeResp implements Serializable {
    private static final long serialVersionUID=1L;
    //订购编号
    private int subReqID;
    //订购结果 0 表示成功
    private int respCode;
    //可选的详细描述信息
    private String desc;

    public int getSubReqID() {
        return subReqID;
    }

    public void setSubReqID(int subReqID) {
        this.subReqID = subReqID;
    }

    public int getRespCode() {
        return respCode;
    }

    public void setRespCode(int respCode) {
        this.respCode = respCode;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String toString(){
        return "SubscribeResp [ subReqID = "+subReqID+" " +
                ", respCode = "+respCode+" , desc = "+desc+" ]";
    }
}

SubscribeReqServer 服务端启动类

public class SubscribeReqServer {
    public void bind(int port){
        //配置服务端的NIO线程组
        EventLoopGroup parentGroup=new NioEventLoopGroup();
        EventLoopGroup childGroup=new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap=new ServerBootstrap();
            bootstrap.group(parentGroup,childGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG,100)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        protected void initChannel(SocketChannel socketChannel) throws Exception {

                            //socketChannel.pipeline().addLast(
                                    //new LengthFieldBasedFrameDecoder(20*1024,0,2));
                            
                            //添加 MarshallingCodeCFactory 构造的 Marshalling对应的解码器和编码器
                           socketChannel.pipeline().
                                   addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
                           socketChannel.pipeline()
                                           .addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
                            socketChannel.pipeline()
                                    .addLast(new SubscribeServerHandler());
                        }
                    });
            ChannelFuture future=bootstrap.bind(port).sync();
            System.out.println("netty server is started");
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //优雅退出,释放线程池资源
            parentGroup.shutdownGracefully();
            childGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        new SubscribeReqServer().bind(8080);
    }
}

MarshallingCodeCFactory

public class MarshallingCodeCFactory {
    public static MarshallingDecoder buildMarshallingDecoder(){
        //通过工具类 Marshalling 的 getProvidedMarshallerFactory 静态方法获取 MarshallerFactory 实例
        //参数 serial 表示创建的是 Java 序列化工厂对象
        final MarshallerFactory marshallerFactory= Marshalling.getProvidedMarshallerFactory("serial");
        //创建 MarshallingConfiguration 对象,将它的版本号设置为5,
        final MarshallingConfiguration configuration=new MarshallingConfiguration();
        configuration.setVersion(5);
        //然后根据  MarshallerFactory 和 MarshallingConfiguration 创建 UnmarshallerProvider 对象
        UnmarshallerProvider provider=new DefaultUnmarshallerProvider(marshallerFactory,configuration);
        //创建 Netty 的 MarshallingDecoder 对象,1024 表示 单个消息序列化后的最大长度
        MarshallingDecoder decoder=new MarshallingDecoder(provider,1024);
        return decoder;
    }

    public static MarshallingEncoder buildMarshallingEncoder(){
        //构造 MarshallerFactory 对象
        final MarshallerFactory marshallerFactory=Marshalling.getProvidedMarshallerFactory("serial");
        //构造 MarshallingConfiguration 对象
        final MarshallingConfiguration configuration=new MarshallingConfiguration();
        configuration.setVersion(5);
        //利用  MarshallerFactory MarshallingConfiguration 来 构造 MarshallerProvider对象
        MarshallerProvider provider=new DefaultMarshallerProvider(marshallerFactory,configuration);
        //创建 Netty 的解码器 MarshallingEncoder
        MarshallingEncoder encoder=new MarshallingEncoder(provider);
        return encoder;
    }
}

服务端业务处理类 SubscribeServerHandler

public class SubscribeServerHandler extends ChannelHandlerAdapter {

    public void channelRead(ChannelHandlerContext context,Object obj){
        SubscribeReq subscribeReq=(SubscribeReq)obj;
        //对合法性进行交易,当前只校验userName属性。如果符合,将信息发送给客户端
        if ("echo".equals(subscribeReq.getUserName())){
            System.out.println("Service accept client subscribe req : "+subscribeReq);
            context.writeAndFlush(resp(subscribeReq.getSubReqID()));
        }
    }

    private SubscribeResp resp(int subId){
        SubscribeResp subscribeResp=new SubscribeResp();
        subscribeResp.setSubReqID(subId);
        subscribeResp.setRespCode(0);
        subscribeResp.setDesc("Netty learning is doing,please go on .");
        return subscribeResp;
    }

    public void exceptionCaught(ChannelHandlerContext context,Throwable throwable){
        throwable.printStackTrace();
        context.close();
    }


}

客户端启动类 SubscribeClient

public class SubscribeClient {

    private void connect(String host, int port) {
        EventLoopGroup workGroup = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(workGroup)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                           // socketChannel.pipeline().addLast(new LengthFieldBasedFrameDecoder(20*1024,0,2));
                            //添加 MarshallingCodeCFactory 构造的 Marshalling对应的解码器和编码器
                            socketChannel.pipeline().
                                    addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
                            socketChannel.pipeline()
                                    .addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
                            socketChannel.pipeline().addLast(new SubscribeClientHandler());

                        }
                    });
            ChannelFuture future=bootstrap.connect(host,port).sync();
            System.out.println("the netty client is started,and connected server");
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //优雅退出
            workGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        new SubscribeClient().connect("127.0.00.1",8080);
    }
}

客户端 业务处理类 SubscribeClientHandler

public class SubscribeClientHandler extends ChannelHandlerAdapter {

    //tcp 链接成功后,就给服务端 循环发送10条信息
    public void channelActive(ChannelHandlerContext context){
        for (int i=0;i<10;i++){
            context.write(subReq(i));
        }
        context.flush();
    }

    private SubscribeReq subReq(int i){
        SubscribeReq subscribeReq=new SubscribeReq();
        subscribeReq.setSubReqID(i);
        subscribeReq.setAddress("深圳市宝安区西乡街道xxx");
        subscribeReq.setPhoneNumber("174868xxxx");
        subscribeReq.setProductName("Netty learning ");
        subscribeReq.setUserName("echo");
        return  subscribeReq;
    }

    /**
     * 由于对象解码器已经对 SubscribeResp 请求消息 进行了自动解码,
     * 因此
     * @param context
     * @param obj
     */
    public void channelRead(ChannelHandlerContext context,Object obj){
        System.out.println("Receive server response : "+obj);
    }


}

重点部分说明

和前面几章相比,这章相对代码比较简单。重点在于服务端启动类和客户端启动类加的 编码器和解码器。

效果展示

服务端打印

在这里插入图片描述

客户端打印

在这里插入图片描述

踩坑说明

此时用网络注释 netAssist 来测试服务端,给服务端发送消息的时候,会报异常。如截图:
netAssis 下载地址:https://download.csdn.net/download/echohuangshihuxue/87311946?spm=1001.2014.3001.5503
在这里插入图片描述

解决办法

在服务端启动类里面,加上一个 LengthFieldBasedFrameDecoder 这个解码器即可。
如图:
在这里插入图片描述

总结

本章介绍了如何使用Netty的Marshalling 编码器和解码器对POJO对象进行序列化。通过使用Netty的
Marshalling 编解码器,我们可以轻松的开发出支持 JBoss Marshalling 序列化的客户端和服务端程序,
方便对接JBoss 的内部模块,同时也利于对已有使用JBoss Marshalling 框架做通信协议的模块的桥接和重用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/150699.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

leetcode.2471 逐层排序二叉树所需的最少操作数目 - bfs + 置换环算法 + 并查集

2471. 逐层排序二叉树所需的最少操作数目 目录 1、循环标记置换环 2、并查集置换环 思路&#xff1a; 总操作数目 每一层最小操作数之和 每一层元素个数 - 置换环数 先用bfs对树进行层序遍历&#xff0c;一层一层地计算 置换环&#xff1a;对每个节点&#xff0c;将其指向…

全国首例:新一代仿生型人工心脏在福建成功植入

此时此刻&#xff0c;福建福清吴先生的体内正搏动着一颗新款的“人工心脏”。心脏是生命的中枢&#xff0c;一旦衰竭生命也将终止&#xff0c;人工心脏为这些心衰患者带来了新的希望。福建医科大学附属协和医院心外科团队&#xff0c;将科幻电影里装着人工心脏的“钢铁侠”变成…

六派巨量转移技术概述

1. 巨量转移技术概述 与OLED显示技术不同&#xff0c;无机LED无法在玻璃或其他大尺寸衬底进行大面积的制作&#xff0c;因此需要在半导体衬底上进行制作&#xff0c;然后再转移到驱动背板上。当前LED所采用的衬底一般为蓝宝石&#xff0c;但蓝宝石与外延层之间的晶格和热膨胀系…

国产技术迎来突破,光量子芯片横空出世,中文编程也有好消息

国外光刻机不再牛&#xff0c;随着这项技术问世&#xff0c;我们摆脱芯片卡脖子困境成为可能&#xff01; 欧美技术如此领先&#xff0c;我们凭什么实现弯道超车&#xff1f;就凭国内领先全球的量子技术&#xff0c;还有惊艳问世的光量子芯片&#xff0c;让欧美震惊不已&#x…

Fossid简介及API接口调用开发

FOSSID简介 FOSSID 是由瑞典FOSSID 公司开发的一款开源代码检测和管理工具&#xff0c;能够全面、准确、高效的发现用户代码库中的开源代码及其风险。 FOSSID 是一个软件解决方案&#xff0c;能够单独部署使用&#xff0c;也可以与现有的开发流程进行无缝集成&#xff0c;能够…

Apache Shiro教程(4)

shiro授权 授权 授权&#xff0c;即访问控制&#xff0c;控制谁能访问哪些资源&#xff0c;主体进行身份认证后需要分配权限方可访问系统的资源&#xff0c;对于某些资源没有权限是无法访问的。 关键对象 授权可简单理解为 who 对 what 进行how操作 授权流程 授权方式 基于角…

如何优化Blender内存不足问题

众所周知&#xff0c; Blender是一款免费软件&#xff0c;在动画、3D 电影等所有领域都易于使用。您是否曾经在 Blender 场景中工作&#xff0c;突然无缘无故崩溃&#xff1f;或者简单地说&#xff0c;您在渲染过程中突然移动缓慢甚至导致卡顿。当你有最后期限时&#xff0c;这…

13_4、Java的IO流之缓冲流的使用

一、引入为了提高数据读写的速度&#xff0c;Java API提供了带缓冲功能的流类&#xff0c;在使用这些流类 时&#xff0c;会创建一个内部缓冲区数组&#xff0c;缺省使用8192个字节(8Kb)的缓冲区。 二、缓冲流涉及到的类字节输入流&#xff1a;BufferedInputStream 字节输出流B…

pytorch入门理解

一、入门操作 1、创一个tensor矩阵 x torch.rand(5, 3) x out&#xff1a; tensor([[0.5051, 0.7017, 0.0170],[0.1441, 0.2476, 0.5710],[0.0452, 0.8690, 0.2387],[0.5709, 0.0098, 0.6993],[0.3203, 0.5124, 0.1010]])创建好后可以直接打印&#xff0c;要比tensorflow好用…

【SQL时间截取】数据库Sql实现截取时间段和日期

【写在前面】前些日子接到这样的需求&#xff0c;我们要对用户访问网站的时间做个统计&#xff0c;但是我想统计到具体的时间点&#xff0c;便于统计不同时间段&#xff08;上午、下午、傍晚、凌晨&#xff09;访问的人数占比。 数据库Sql实现截取时间段和日期1、原始数据查看2…

【云原生】k8s之Ingress

内容预知 1.Ingress的相关知识 1.1 Ingress的简介 1.2 Ingress 的组成 1.3 Ingress-Nginx的工作原理 1.4 新生代Ingress-controller &#xff08;Traefik&#xff09; Ingress-nginx和Ingress-Traefik的简单对比 1.5 Ingress的暴露方式 方式一&#xff1a;DeploymentLoad…

ocr票据证件信息抽取正则化

Python 正则表达式 | 菜鸟教程Python 正则表达式 正则表达式是一个特殊的字符序列&#xff0c;它能帮助你方便的检查一个字符串是否与某种模式匹配。Python 自1.5版本起增加了re 模块&#xff0c;它提供 Perl 风格的正则表达式模式。 re 模块使 Python 语言拥有全部的正则表达式…

华为数字化转型之道 实践篇 第九章 数字化运营:实现业务运营模式升级

第九章 数字化运营:实现业务运营模式升级 业务运营是为了帮助企业基于自身业务战略,更好地达成企业经营与运营目标,这中间包含业务沿着流程周而复始地运转,以及在作业过程中识别并推动问题解决等过程。 而数字化运营旨在利用数字技术获取、管理和分析数据,为企业的战略决…

[ 常用工具篇 ] burpsuite_pro 安装配置详解(附安装包)

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

【矩阵论】5. 线性空间与线性变换——线性空间

矩阵论 1. 准备知识——复数域上矩阵,Hermite变换) 1.准备知识——复数域上的内积域正交阵 1.准备知识——Hermite阵&#xff0c;二次型&#xff0c;矩阵合同&#xff0c;正定阵&#xff0c;幂0阵&#xff0c;幂等阵&#xff0c;矩阵的秩 2. 矩阵分解——SVD准备知识——奇异值…

JVM调优学习

JVM 介绍 1 什么是 JVM JVM 是 Java Virtual Machine&#xff08;Java 虚拟机&#xff09;的缩写。一台执行 Java 程序的机器。 2 JAVA 语言的执行原理 计算机语言&#xff1a; 计算机能够直接执行的指令。这种指令和系统及硬件有关。 计算机高级语言&#xff1a; 在遵循语…

主机加固对服务器防勒索病毒有哪些好处

​ 近年来&#xff0c;计算机以及互联网应用在中国得到普及和发展&#xff0c;已经深入到社会每个角落&#xff0c;政府&#xff0c;经济&#xff0c;军事&#xff0c;社会&#xff0c;文化和人们生活等各方面都越来越依赖于计算机和网络&#xff0c;电子政务&#xff0c;无纸办…

排列树和子集树

排列树 输出数组的全排列 排列问题&#xff1a; 设R {r1,r2,r3,…,rn}是要排列的n个元素&#xff0c;Ri R - {r1} 集合X中元素的全排列记为perm(X)。(ri)perm(x)便是在全排列perm(X)的每一个排列前加上前缀ri得到的排列。 R的全排列&#xff1a; n1时&…

通信电子、嵌入式类面试题刷题计划02

文章目录011——单片机上电后没有运转&#xff0c;首先要检查什么&#xff1f;【校招】012——请描述你对数字IC的认识【实习】013——电脑的组成&#xff0c;细化到显卡之类的【软件/硬件测试】014——黑盒测试和白盒测试的区别? 【软件/硬件测试】015——名词扩写&#xff1…

【C语言开源项目】tinyhttpd ——下载、安装、使用

前言 本系列将带领大家看一些C语言的优秀的开源项目&#xff0c;并逐步深入讲解源码&#xff0c;感兴趣的可以点击关注、收藏&#xff0c;有问题及时在评论区评论~ Tinyhttpd 介绍 Tinyhttpd 是一个非常轻量级的 web server&#xff0c;总共只有500多行代码&#xff0c;非常…