kryo、fst实现序列化

一、fst

介绍:FST fast-serialization 是重新实现的 Java 快速对象序列化的开发包
开源地址https://gitee.com/mirrors/fst
依赖

        <!-- https://mvnrepository.com/artifact/de.ruedigermoeller/fst -->
        <dependency>
            <groupId>de.ruedigermoeller</groupId>
            <artifactId>fst</artifactId>
            <version>2.57</version>
        </dependency>

代码实现

import lombok.Data;
import org.nustaq.serialization.FSTConfiguration;
import org.nustaq.serialization.FSTObjectInput;
import org.nustaq.serialization.FSTObjectOutput;
import org.nustaq.serialization.coders.JSONAsString;

import java.io.*;

public class StringText {
    
    

    static FSTConfiguration conf = FSTConfiguration.createAndroidDefaultConfiguration();

    static void writeObject(OutputStream outputStream, FstObject fstObject) throws IOException {
    
    
        FSTObjectOutput out = conf.getObjectOutput(outputStream);
        out.writeObject(fstObject);
        out.close();
    }

    static FstObject readObject(InputStream inputStream) throws Exception {
    
    
        FSTObjectInput input = conf.getObjectInput(inputStream);
        FstObject fstObject = (FstObject) input.readObject(FstObject.class);
        input.close();
        return fstObject;
    }

    @Data
    public static class TS implements Serializable {
    
    
        @JSONAsString
        byte[] bytes;
    }

    @Data
    static class PJ implements Serializable {
    
    
        int a = 10;
    }

    @Data
    public static class FstObject{
    
    
        private String name;
        private int age;
    }
    
    // 2种配置 实现不同
    public static void main(String[] args) throws UnsupportedEncodingException {
    
    
        TS t = new TS();
        FSTConfiguration conf = FSTConfiguration.createJsonConfiguration(true,false);
        byte[] bytes = conf.asByteArray(t);
        System.out.println(new String(bytes,"UTF-8"));
        FSTConfiguration fst = FSTConfiguration.createJsonConfiguration();
        PJ pojo = new PJ();
        String x = fst.asJsonString(pojo);
        System.out.println(x);

        FSTConfiguration conks = FSTConfiguration.createAndroidDefaultConfiguration();
        FstObject object = new FstObject();
        object.setName("test");
        object.setAge(30);
        System.out.println("serialization, " + object);
        byte[] bytes1 = conks.asByteArray(object);
        FstObject newObject = (FstObject) conks.asObject(bytes1);
        System.out.println("deSerialization, " + newObject);
    }
}

二、kryo

介绍:Kryo是用于Java的快速高效的二进制对象图序列化框架。该项目的目标是高速,小尺寸和易于使用的API。每当需要将对象持久保存到文件,数据库还是通过网络时,该项目都是有用的。
Kryo还可以执行自动的深浅复制/克隆。这是从对象到对象的直接复制,而不是从对象到字节的复制。

开源地址https://github.com/EsotericSoftware/kryo
依赖

        <!--可能会与业务现有依赖的asm产生冲突-->
        <!-- https://mvnrepository.com/artifact/com.esotericsoftware/kryo -->
        <dependency>
            <groupId>com.esotericsoftware</groupId>
            <artifactId>kryo-shaded</artifactId>
            <version>4.0.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.objenesis/objenesis -->
        <!-- 用于实例化Java对象的库 -->
		<dependency>
		    <groupId>org.objenesis</groupId>
		    <artifactId>objenesis</artifactId>
		    <version>3.1</version>
		</dependency>

代码实现

public interface Serializer {
    
    

    /**
     * 序列化
     * @param object
     * @param bytes
     */
    void serializer(Object object,byte[] bytes);

    /**
     *
     * @param object
     * @param bytes
     * @param offset
     * @param count
     */
    void serializer(Object object,byte[] bytes,int offset,int count);

    /**
     * 反序列化
     * @param bytes
     * @param <T>
     * @return
     */
    <T> T deserializer(byte[] bytes);

    /**
     * 反序列化
     * @param bytes
     * @param offset
     * @param count
     * @param <T>
     * @return
     */
    <T> T deserializer(byte[] bytes,int offset,int count);
}
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.serializers.BeanSerializer;
import org.objenesis.strategy.StdInstantiatorStrategy;
import org.springframework.stereotype.Component;


/**
 * kryo实现序列化和反序列化接口
 * kryo不是线程安全的,需要注意,使用独立线程实现
 */
@Component
public class KryoSerializer implements Serializer {
    
    

    //将kryo对象存储在线程中,只有这个线程可以访问到,这样保证kryo的线程安全性,ThreadLocal(线程内部存储类)
    //通过get()&set()方法读取线程内的数据
    private final ThreadLocal<Kryo> kryoThreadLocal = new ThreadLocal<Kryo>(){
    
    
        @Override
        protected Kryo initialValue() {
    
    
            Kryo kryo = new Kryo();
            kryo.register(aClass, new BeanSerializer<>(kryo,aClass));
            //引用,对A对象序列化时,默认情况下kryo会在每个成员对象第一次序列化时写入一个数字,
            // 该数字逻辑上就代表了对该成员对象的引用,如果后续有引用指向该成员对象,
            // 则直接序列化之前存入的数字即可,而不需要再次序列化对象本身。
            // 这种默认策略对于成员存在互相引用的情况较有利,否则就会造成空间浪费
            // (因为没序列化一个成员对象,都多序列化一个数字),
            // 通常情况下可以将该策略关闭,kryo.setReferences(false);
            kryo.setReferences(false);
            //设置是否注册全限定名,
            kryo.setRegistrationRequired(false);
            //设置初始化策略,如果没有默认无参构造器,那么就需要设置此项,使用此策略构造一个无参构造器
            kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
            return kryo;
        }
    };

    private final  ThreadLocal<Output> outputThreadLocal = new ThreadLocal<>();

    private final  ThreadLocal<Input> inputThreadLocal = new ThreadLocal<>();

    private Class<?> aClass = null;


    public Class<?> getaClass() {
    
    
        return aClass;
    }

    public void setaClass(Class<?> aClass) {
    
    
        this.aClass = aClass;
    }

    @Override
    public void serializer(Object object, byte[] bytes) {
    
    
        Kryo kryo = kryoThreadLocal.get();
        Output output =getOutPut(bytes);
        kryo.writeObjectOrNull(output,object,object.getClass());
        output.flush();
    }

    @Override
    public void serializer(Object object, byte[] bytes, int offset, int count) {
    
    
        Kryo kryo = kryoThreadLocal.get();
        Output output =getOutPut(bytes,offset,count);
        kryo.writeObjectOrNull(output,object,object.getClass());
        output.flush();
    }

    @Override
    public <T> T deserializer(byte[] bytes) {
    
    
        Kryo kryo =  kryoThreadLocal.get();
        Input input = getInPut(bytes);
        return (T)kryo.readObjectOrNull(input,aClass);
    }

    @Override
    public <T> T deserializer(byte[] bytes, int offset, int count){
    
    
        Kryo kryo = kryoThreadLocal.get();
        Input input = getInPut(bytes,offset,count);
        return (T)kryo.readObjectOrNull(input,aClass);
    }

    private Output getOutPut(byte[] bytes){
    
    
        Output output = outputThreadLocal.get();
        if(output == null){
    
    
            output = new Output();
            outputThreadLocal.set(new Output());
        }
        if(bytes!=null){
    
    
            output.setBuffer(bytes);
        }
        return output;
    }
    private Output getOutPut(byte[] bytes,int offset,int count){
    
    
        Output output = outputThreadLocal.get();
        if(output == null){
    
    
            output = new Output();
            outputThreadLocal.set(new Output());
        }
        if(bytes!=null){
    
    
            output.writeBytes(bytes,offset,count);
        }
        return output;
    }
    private Input getInPut(byte[] bytes){
    
    
        Input input = inputThreadLocal.get();
        if(input == null){
    
    
            input= new Input();
            outputThreadLocal.set(new Output());
        }
        if(bytes!=null){
    
    
            input.setBuffer(bytes);
        }
        return input;
    }

    private Input getInPut(byte[] bytes,int offser,int count){
    
    
        Input input = inputThreadLocal.get();
        if(input == null){
    
    
            input= new Input();
            outputThreadLocal.set(new Output());
        }
        if(bytes!=null){
    
    
            input.setBuffer(bytes,offser,count);
        }
        return input;
    }
}

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.pool.KryoPool;
import lombok.Data;
import org.objenesis.strategy.StdInstantiatorStrategy;

import java.util.Arrays;
import java.util.List;

/**
 * kryo的对象本身不是线程安全的,所以我们有两种选择来保障线程安全。
 */
public class KryoTest {
    
    

    private static final ThreadLocal<Kryo> kryoLocal = ThreadLocal.withInitial(() -> {
    
    
        Kryo kryo = new Kryo();
        kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(
                new StdInstantiatorStrategy()));
        return kryo;
    });



    public KryoPool newKryoPool() {
    
    
        return new KryoPool.Builder(() -> {
    
    
            final Kryo kryo = new Kryo();
            kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(
                    new StdInstantiatorStrategy()));
            return kryo;
        }).softReferences().build();
    }

    public static void main(String[] args) {
    
    
        byte[] bytes =new byte[200];
        String[] strings = {
    
    "s1","s2"};
        System.out.println(Arrays.toString(bytes));
        
        KryoSerializer kryoSerializer = new KryoSerializer();
        kryoSerializer.setaClass(TestSerialization.class);
        TestSerialization testSerialization = new TestSerialization();
        testSerialization.setText("test1");
        testSerialization.setName("test2");
        testSerialization.setId(1);
        testSerialization.setFlag(false);
        testSerialization.setList(Arrays.asList(strings));
        kryoSerializer.serializer(testSerialization, bytes);
        System.out.println(testSerialization.toString());
       
        System.out.println(Arrays.toString(bytes));
       
        TestSerialization testSerialization1 = kryoSerializer.deserializer(bytes);
        System.out.println(testSerialization1.toString());
        System.out.println(Arrays.toString(bytes));
    }

    @Data
    public static class TestSerialization {
    
    
        private int id;
        private String text;
        private String name;
        private boolean flag;
        private List<String> list;
    }
}

三、请求与响应测试

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_32447301/article/details/108372812