百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

netty系列之:使用Jboss Marshalling来序列化java对象

ccwgpt 2025-05-15 16:59 3 浏览 0 评论

简介

在JAVA程序中经常会用到序列化的场景,除了JDK自身提供的Serializable之外,还有一些第三方的产品可以实现对JAVA对象的序列化。其中比较有名的就是Google protobuf。当然,也有其他的比较出名的序列化工具,比如Kryo和JBoss Marshalling。

今天想给大家介绍的就是JBoss Marshalling,为什么要介绍JBoss Marshalling呢?

用过google protobuf的朋友可能都知道,虽然protobuf好用,但是需要先定义序列化对象的结构才能生成对应的protobuf文件。如果怕麻烦的朋友可能就不想考虑了。

JBoss Marshalling就是在JDK自带的java.io.Serializable中进行优化的一个序列化工具,用起来非常的简单,并且和java.io.Serializable兼容,所以是居家必备开发程序的好帮手。

根据JBoss官方的介绍,JBoss Marshalling和JDK java.io.Serializable相比有两个非常大的优点,第一个优点就是JBoss Marshalling解决了java.io.Serializable中使用的一些不便和问题。第二个优点就是JBoss Marshalling完全是可插拔的,这样就提供了对JBoss Marshalling框架进行扩展的可能,那么一起来看看JBoss Marshalling的使用吧。

添加JBoss Marshalling依赖

如果想用JBoss Marshalling,那么第一步就是添加JBoss Marshalling的依赖。

很奇怪的是如果你到JBoss Marshalling的官网上,可能会发现JBoss Marshalling很久都没有更新了,它的最新版本还是2011-04-27年出的1.3.0.CR9版本。

但是不要急,如果你去maven仓库搜一下,会发现最新的版本是2021年5月发行的2.0.12.Final版本。

所以这里我们就拿最新的2.0.12.Final版本为例进行讲解。

如果仔细观察JBoss Marshalling的maven仓库,可以看到JBoss Marshalling包含了4个依赖包,分别是JBoss Marshalling API,JBoss Marshalling River Protocol,JBoss Marshalling Serial Protocol和JBoss Marshalling OSGi Bundle。

JBoss Marshalling API是我们在程序中需要调用的API接口,这个是必须要包含的。JBoss Marshalling River Protocol和JBoss Marshalling Serial Protocol是marshalling的两种实现方式,可以根据需要自行取舍。

JBoss官网并没有太多关于这两个序列化实现的细节,我只能说,根据我的了解river的压缩程度更高。其他更多细节和实现可能只有具体阅读源码才知道了。

JBoss Marshalling OSGi Bundle是一个基于OSGi的可插拔的框架。

如果我们只是做对象的序列化,那么只需要使用JBoss Marshalling API和JBoss Marshalling River Protocol就行了。

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

JBoss Marshalling的使用

添加了依赖之后,我们就可以开始使用JBoss Marshalling了。JBoss Marshalling的使用非常简单,首先我们要根据选择的marshalling方式创建MarshallerFactory:

 // 使用river作为marshalling的方式
        MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("river");

这里我们选择使用river作为marshalling的序列化方式。

有了MarshallerFactory,我们还需要一个MarshallingConfiguration为MarshallerFactory提供一些必要的序列化参数。

一般来说,我们可以控制MarshallingConfiguration的下面一些属性:

MarshallingConfiguration configuration = new MarshallingConfiguration();
 configuration.setVersion(4);
 configuration.setClassCount(10);
 configuration.setBufferSize(8096);
 configuration.setInstanceCount(100);
 configuration.setExceptionListener(new MarshallingException());
 configuration.setClassResolver(new SimpleClassResolver(getClass().getClassLoader()));

setVersion是设置使用的marshalling protocol的版本号,这个版本号非常重要,因为依赖的protocol实现可能根据会根据需要进行序列化实现的升级,可能产生不兼容的情况。通过设置版本号,可以保证升级之后的protocol也能兼容之前的序列化版本。

setClassCount是预设要序列化对象中的class个数。

setInstanceCount是预设序列化对象中的class实例个数。

setBufferSize设置读取数据的buff大小,通过调节这个属性可以调整序列化的性能。

setExceptionListener添加序列化异常的时候的异常监听器。

setClassResolver用来设置classloader。

JBoss Marshalling的强大之处在于我们在序列化的过程中还可以对对象进行拦截,从而进行日志输出或者其他的业务操作。

configuration提供了两个方法,分别是setObjectPreResolver和setObjectResolver。

这两个方法接受一个ObjectResolver对象,可以用来对对象进行处理。

两个方法的不同在于执行的顺序,preResolver在所有的resolver之前执行。

做好上面的配置之后,我们就可以正式开始编码了。

            final Marshaller marshaller = marshallerFactory.createMarshaller(configuration);
            try(FileOutputStream os = new FileOutputStream(fileName)){
                marshaller.start(Marshalling.createByteOutput(os));
                marshaller.writeObject(obj);
                marshaller.finish();
            }

上面的例子中,通过调用marshaller的start方法开启序列化,然后调用marshaller.writeObject写入对象。

最后调用marshaller.finish结束序列化。

整个序列化的代码如下所示:

    public void marshallingWrite(String fileName, Object obj) throws IOException {
        // 使用river作为marshalling的方式
        MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("river");
        // 创建marshalling的配置
        MarshallingConfiguration configuration = new MarshallingConfiguration();
        // 使用版本号4
        configuration.setVersion(4);

            final Marshaller marshaller = marshallerFactory.createMarshaller(configuration);
            try(FileOutputStream os = new FileOutputStream(fileName)){
                marshaller.start(Marshalling.createByteOutput(os));
                marshaller.writeObject(obj);
                marshaller.finish();
            }
    }

    public static void main(String[] args) throws IOException {
        MarshallingWriter writer = new MarshallingWriter();
        Student student= new Student("jack", 18, "first grade");
        writer.marshallingWrite("/tmp/marshall.txt",student);
    }

非常的简洁明了。

注意,这里我们序列化了一个Student对象,这个对象一定要实现java.io.Serializable接口,否则会抛出类型下面的异常:

Exception in thread "main" java.io.NotSerializableException: 
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:274)
    at org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:58)
    at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:111)

接下来就是序列化的反向动作反序列化了。

代码很简单,我们直接上代码:

   public void marshallingRead(String fileName) throws IOException, ClassNotFoundException {
        // 使用river协议创建MarshallerFactory
        MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("river");
        // 创建配置文件
        MarshallingConfiguration configuration = new MarshallingConfiguration();
        // 使用版本号4
        configuration.setVersion(4);
            final Unmarshaller unmarshaller = marshallerFactory.createUnmarshaller(configuration);
            try(FileInputStream is = new FileInputStream(fileName)){
                unmarshaller.start(Marshalling.createByteInput(is));
                Student student=(Student)unmarshaller.readObject();
                log.info("student:{}",student);
                unmarshaller.finish();
            }
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        MarshallingReader reader= new MarshallingReader();
        reader.marshallingRead("/tmp/marshall.txt");
    }

运行上面的代码,我们可能得到下面的输出:

[main] INFO  c.f.marshalling.MarshallingReader - student:Student(name=jack, age=18, className=first grade)

可见读取序列化的对象已经成功。

总结

以上就是JBoss Marshalling的基本使用。通常对我们程序员来说,这个基本的使用已经足够了。除非你有根据复杂的序列化需求,比如对象中的密码需要在序列化的过程中进行替换,这种需求可以使用我们前面提到的ObjectResolver来实现。

本文的例子可以参考:learn-netty4

本文已收录于
http://www.flydean.com/17-jboss-marshalling/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

相关推荐

netty系列之:使用Jboss Marshalling来序列化java对象

简介在JAVA程序中经常会用到序列化的场景,除了JDK自身提供的Serializable之外,还有一些第三方的产品可以实现对JAVA对象的序列化。其中比较有名的就是Googleprotobuf。当然...

6款可替代dreamweaver的工具

dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver...

Java—类加载的基本机制和过程

类加载的基本机制和过程运行Java程序,就是执行java这个命令,指定包含main方法的完整类名,以及一个classpath,即类路径。类路径可以有多个,对于直接的class文件,路径是class文件...

什么是双亲委派机制?(转载)

原文章地址:https://www.cnblogs.com/hollischuang/p/14260801.html什么是双亲委派机制首先,我们知道,虚拟机在加载类的过程中需要使用类加载器进行加载,而...

[架构师必看]我在系统设计上犯过的14个错

在上篇《架构师画像》的文章中提到了自己在系统设计上犯过的一些错,觉得还挺有意义的,这篇文章就来回顾下自己近八年来所做的一些系统设计,看看犯的一些比较大的血淋淋的错误(很多都是推倒重来),这八年来主要做...

ONOS架构之子系统介绍

前言:为了方便灵活性,ONOS采取的是一种模块化结构,一方面能灵活地组织各种模块,容易让开发者扩展出新的模块,同时通过隔离令系统的模块各司其职而不会互相干扰。实际上ONOS是由多个子系统组成,本文将对...

基于微信小程序的在线课堂系统设计与实现-计算机毕业设计源码

摘要随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,在线课堂微信小程序被用户普遍使用,为方便用户能够...

微信小程序云开发教室预约系统的前后端交互与数据库设计

需求描述:需要申请使用教室时,可点击教室申请查看教室的使用状况及相关设备。确定好需要的教室后,按学期、校区、教学楼、周次、星期、节次、等维度筛选,并备注用途。例如:当我点击该教室申请占用后,该教室状态...

微信小程序开发准备材料以及方式

这里讲述小程序注册类型为企业类型时所需要的资料,首先需要一个新的邮箱号,作为登陆账号,需要管理员或者法人的身份信息、已绑定银行卡的微信号、手机号、营业执照、开户银行信息,或者一些特殊行业所需要的办理的...

webman 事务回滚失效问题记录

大家好,我是yangyang.最近有用到webman这个框架写业务,写代码的过程中,遇到了一个奇葩的问题:基于webman下使用laravel的orm组件事务回滚不生效简单介绍下webmanwebma...

PHP实时通信:Workerman篇

一般做Web开发,用的是HTTP协议进行通信,是一个简单的请求-响应协议。做PHP开发的都很清楚这一点。只能由浏览器发起请求,服务器响应内容。服务器不能主动向浏览器推送消息。多个浏览器之间也不能互相发...

PHP培训课程内容都有哪些?PHP培训哪些内容?

作为一门经久不衰的开发语言,php开发工程师一直是很多年轻人选择学习和就业的职业方向,那么PHP培训课程主要学习哪些内容呢?一、企业级开发专题:深入剖析企业实际开发过程,教授最实用的企业级技术PHP7...

go 和 php 性能如何进行对比?

PHP性能很差吗?每次讲到PHP和其他语言间的性能对比,似乎都会发现这样一个声音:单纯的性能对比没有意义,主要瓶颈首先是数据库,其次是业务代码等等。好像PHP的性能真的不能单独拿出来讨论似的。但其实一...

突然发现php工作变少了

突然发现php工作变少了。好像不大行了,被go取代了魔法涂鸦python和php对比如下:1.python依赖管理需然简单,但依赖本身做的比较宽松,一但版本更新,或修改,就有一堆问题;2.传统py...

php高并发的瓶颈到底在哪

php高并发的瓶颈到底在哪?是同步阻塞?还是nginx+fpm不断创建-销毁进程资源过度消耗?高并发到底是什么问题,是语言问题嘛,为什么说php不适合高并发?求大佬指点从2009年后一直用lnmp,从...

取消回复欢迎 发表评论: