Introduction

Serialization is often used in JAVA programs. In addition to the Serializable provided by JDK itself, there are some third-party products that can serialize JAVA objects. One of the more famous ones is Google protobuf. Of course, there are other well-known serialization tools, such as Kryo and JBoss Marshalling.

What I want to introduce to you today is JBoss Marshalling. Why introduce JBoss Marshalling?

Friends who have used google protobuf may know that although protobuf is easy to use, it is necessary to define the structure of the serialized object before generating the corresponding protobuf file. Friends who are afraid of trouble may not want to consider it.

JBoss Marshalling is a serialization tool optimized in the java.io.Serializable that comes with JDK. It is very simple to use and compatible with java.io.Serializable, so it is a good helper for home development programs.

According to the official introduction of JBoss, JBoss Marshalling has two very big advantages compared with JDK java.io.Serializable. The first advantage is that JBoss Marshalling solves some inconveniences and problems used in java.io.Serializable. The second advantage is that JBoss Marshalling is completely pluggable, which provides the possibility to extend the JBoss Marshalling framework. Let's take a look at the use of JBoss Marshalling.

Add JBoss Marshalling dependency

If you want to use JBoss Marshalling, the first step is to add the dependencies of JBoss Marshalling.

It is very strange that if you go to the official website of JBoss Marshalling, you may find that JBoss Marshalling has not been updated for a long time, and its latest version is version 1.3.0.CR9 released in 2011-04-27.

But don't worry, if you go to the maven repository to search, you will find that the latest version is the 2.0.12.Final version released in May 2021.

So here we take the latest version 2.0.12.Final as an example to explain.

If you look closely at the maven repository of JBoss Marshalling, you can see that JBoss Marshalling contains 4 dependencies, namely JBoss Marshalling API, JBoss Marshalling River Protocol, JBoss Marshalling Serial Protocol and JBoss Marshalling OSGi Bundle.

The JBoss Marshalling API is the API interface that we need to call in the program, which must be included. JBoss Marshalling River Protocol and JBoss Marshalling Serial Protocol are two implementations of marshalling, and you can choose between them according to your needs.

The official website of JBoss doesn't have too many details about the implementation of these two serializations. I can only say that according to my understanding, the compression degree of the river is higher. Other more details and implementations may only be known by reading the source code.

JBoss Marshalling OSGi Bundle is an OSGi-based pluggable framework.

If we're just doing object serialization, then just use the JBoss Marshalling API and the 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>

Use of JBoss Marshalling

After adding the dependencies, we can start using JBoss Marshalling. The use of JBoss Marshalling is very simple. First, we need to create a MarshallerFactory according to the selected marshalling method:

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

Here we choose to use river as the serialization method of marshalling.

With the MarshallerFactory, we also need a MarshallingConfiguration to provide the MarshallerFactory with some necessary serialization parameters.

In general, we can control the following properties of 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 is to set the version number of the marshalling protocol used. This version number is very important, because the dependent protocol implementation may be upgraded according to the needs of the serialization implementation, which may cause incompatibility. By setting the version number, you can ensure that the upgraded protocol is also compatible with the previous serialized version.

setClassCount is the number of classes in the preset object to be serialized.

setInstanceCount is the number of class instances in the preset serialized object.

setBufferSize sets the buff size of the read data. By adjusting this property, the serialization performance can be adjusted.

setExceptionListener adds an exception listener when serializing exceptions.

setClassResolver is used to set the classloader.

The power of JBoss Marshalling is that we can also intercept objects during the serialization process to perform log output or other business operations.

Configuration provides two methods, setObjectPreResolver and setObjectResolver.

These two methods accept an ObjectResolver object that can be used to process the object.

The difference between the two methods is the order of execution, preResolver is executed before all resolvers.

After doing the above configuration, we can officially start coding.

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

In the above example, serialization is enabled by calling the marshaller's start method, and then calling marshaller.writeObject to write the object.

Finally, call marshaller.finish to end serialization.

The entire serialized code looks like this:

 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);
    }

Very concise and clear.

Note that here we serialize a Student object, which must implement the java.io.Serializable interface, otherwise the following exception will be thrown:

 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)

The next step is to deserialize the reverse action of serialization.

The code is very simple, we go directly to the code:

 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");
    }

Running the above code, we might get the following output:

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

It can be seen that the serialized object has been successfully read.

Summarize

The above is the basic use of JBoss Marshalling. Usually this basic usage is enough for us programmers. Unless you have complex serialization requirements, such as the password in the object needs to be replaced during the serialization process, this requirement can be achieved using the ObjectResolver we mentioned earlier.

Examples of this article can refer to: learn-netty4

This article has been included in http://www.flydean.com/17-jboss-marshalling/

The most popular interpretation, the most profound dry goods, the most concise tutorials, and many tricks you don't know are waiting for you to discover!

Welcome to pay attention to my official account: "Program those things", understand technology, understand you better!


flydean
890 声望437 粉丝

欢迎访问我的个人网站:www.flydean.com