kryo、fst实现序列化

tech2022-08-20  120

一、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; } }

三、请求与响应测试

最新回复(0)