介绍: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是用于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
* @return
*/
<T> T deserializer(byte[] bytes);
/**
* 反序列化
* @param bytes
* @param offset
* @param count
* @param
* @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;
}
}