Skip to content

Commit 1005e48

Browse files
committed
update docs
1 parent bd88a39 commit 1005e48

1 file changed

Lines changed: 192 additions & 7 deletions

File tree

docs/javalib/javalib-binary.md

Lines changed: 192 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,48 @@ Java 自身的序列化方式具有以下缺点:
108108
示例:
109109

110110
```java
111+
import org.nustaq.serialization.FSTConfiguration;
112+
113+
import java.io.IOException;
114+
import java.nio.charset.StandardCharsets;
115+
import java.util.Base64;
116+
111117
public class FstDemo {
112118

113119
private static FSTConfiguration DEFAULT_CONFIG = FSTConfiguration.createDefaultConfiguration();
114120

115-
public static <T> byte[] serialize(T obj) {
121+
/**
122+
* 将对象序列化为 byte 数组
123+
*
124+
* @param obj 任意对象
125+
* @param <T> 对象的类型
126+
* @return 序列化后的 byte 数组
127+
*/
128+
public static <T> byte[] writeToBytes(T obj) {
116129
return DEFAULT_CONFIG.asByteArray(obj);
117130
}
118131

119-
public static <T> T deserialize(byte[] bytes, Class<T> clazz) throws IOException {
132+
/**
133+
* 将对象序列化为 byte 数组后,再使用 Base64 编码
134+
*
135+
* @param obj 任意对象
136+
* @param <T> 对象的类型
137+
* @return 序列化后的字符串
138+
*/
139+
public static <T> String writeToString(T obj) {
140+
byte[] bytes = writeToBytes(obj);
141+
return new String(Base64.getEncoder().encode(bytes), StandardCharsets.UTF_8);
142+
}
143+
144+
/**
145+
* 将 byte 数组反序列化为原对象
146+
*
147+
* @param bytes {@link #writeToBytes} 方法序列化后的 byte 数组
148+
* @param clazz 原对象的类型
149+
* @param <T> 原对象的类型
150+
* @return 原对象
151+
*/
152+
public static <T> T readFromBytes(byte[] bytes, Class<T> clazz) throws IOException {
120153
Object obj = DEFAULT_CONFIG.asObject(bytes);
121154
if (clazz.isInstance(obj)) {
122155
return (T) obj;
@@ -125,19 +158,171 @@ public class FstDemo {
125158
}
126159
}
127160

161+
/**
162+
* 将字符串反序列化为原对象,先使用 Base64 解码
163+
*
164+
* @param str {@link #writeToString} 方法序列化后的字符串
165+
* @param clazz 原对象的类型
166+
* @param <T> 原对象的类型
167+
* @return 原对象
168+
*/
169+
public static <T> T readFromString(String str, Class<T> clazz) throws IOException {
170+
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
171+
return readFromBytes(Base64.getDecoder().decode(bytes), clazz);
172+
}
173+
128174
}
129175
```
130176

131177
测试:
132178

133179
```java
134-
// 序列化
135-
byte[] bytes = JdkSerializeDemo.serialize(oldBean);
136-
// 反序列化
137-
TestBean newBean = JdkSerializeDemo.deserialize(bytes, TestBean.class);
180+
long begin = System.currentTimeMillis();
181+
for (int i = 0; i < BATCH_SIZE; i++) {
182+
TestBean oldBean = BeanUtils.initJdk8Bean();
183+
byte[] bytes = FstDemo.writeToBytes(oldBean);
184+
TestBean newBean = FstDemo.readFromBytes(bytes, TestBean.class);
185+
}
186+
long end = System.currentTimeMillis();
187+
System.out.printf("FST 序列化/反序列化耗时:%s", (end - begin));
138188
```
139189

140-
## TODO
190+
## Kryo 应用
191+
192+
### 引入依赖
193+
194+
```xml
195+
<dependency>
196+
<groupId>com.esotericsoftware</groupId>
197+
<artifactId>kryo</artifactId>
198+
<version>5.0.0-RC4</version>
199+
</dependency>
200+
```
201+
202+
### Kryo API
203+
204+
示例:
205+
206+
```java
207+
import com.esotericsoftware.kryo.Kryo;
208+
import com.esotericsoftware.kryo.io.Input;
209+
import com.esotericsoftware.kryo.io.Output;
210+
import com.esotericsoftware.kryo.util.DefaultInstantiatorStrategy;
211+
import org.objenesis.strategy.StdInstantiatorStrategy;
212+
213+
import java.io.ByteArrayInputStream;
214+
import java.io.ByteArrayOutputStream;
215+
import java.nio.charset.StandardCharsets;
216+
import java.util.Base64;
217+
218+
public class KryoDemo {
219+
220+
// 每个线程的 Kryo 实例
221+
private static final ThreadLocal<Kryo> kryoLocal = ThreadLocal.withInitial(() -> {
222+
Kryo kryo = new Kryo();
223+
224+
/**
225+
* 不要轻易改变这里的配置!更改之后,序列化的格式就会发生变化,
226+
* 上线的同时就必须清除 Redis 里的所有缓存,
227+
* 否则那些缓存再回来反序列化的时候,就会报错
228+
*/
229+
//支持对象循环引用(否则会栈溢出)
230+
kryo.setReferences(true); //默认值就是 true,添加此行的目的是为了提醒维护者,不要改变这个配置
231+
232+
//不强制要求注册类(注册行为无法保证多个 JVM 内同一个类的注册编号相同;而且业务系统中大量的 Class 也难以一一注册)
233+
kryo.setRegistrationRequired(false); //默认值就是 false,添加此行的目的是为了提醒维护者,不要改变这个配置
234+
235+
//Fix the NPE bug when deserializing Collections.
236+
((DefaultInstantiatorStrategy) kryo.getInstantiatorStrategy())
237+
.setFallbackInstantiatorStrategy(new StdInstantiatorStrategy());
238+
239+
return kryo;
240+
});
241+
242+
/**
243+
* 获得当前线程的 Kryo 实例
244+
*
245+
* @return 当前线程的 Kryo 实例
246+
*/
247+
public static Kryo getInstance() {
248+
return kryoLocal.get();
249+
}
250+
251+
/**
252+
* 将对象序列化为 byte 数组
253+
*
254+
* @param obj 任意对象
255+
* @param <T> 对象的类型
256+
* @return 序列化后的 byte 数组
257+
*/
258+
public static <T> byte[] writeToBytes(T obj) {
259+
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
260+
Output output = new Output(byteArrayOutputStream);
261+
262+
Kryo kryo = getInstance();
263+
kryo.writeObject(output, obj);
264+
output.flush();
265+
266+
return byteArrayOutputStream.toByteArray();
267+
}
268+
269+
/**
270+
* 将对象序列化为 byte 数组后,再使用 Base64 编码
271+
*
272+
* @param obj 任意对象
273+
* @param <T> 对象的类型
274+
* @return 序列化后的字符串
275+
*/
276+
public static <T> String writeToString(T obj) {
277+
byte[] bytes = writeToBytes(obj);
278+
return new String(Base64.getEncoder().encode(bytes), StandardCharsets.UTF_8);
279+
}
280+
281+
/**
282+
* 将 byte 数组反序列化为原对象
283+
*
284+
* @param bytes {@link #writeToBytes} 方法序列化后的 byte 数组
285+
* @param clazz 原对象的类型
286+
* @param <T> 原对象的类型
287+
* @return 原对象
288+
*/
289+
@SuppressWarnings("unchecked")
290+
public static <T> T readFromBytes(byte[] bytes, Class<T> clazz) {
291+
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
292+
Input input = new Input(byteArrayInputStream);
293+
294+
Kryo kryo = getInstance();
295+
return (T) kryo.readObject(input, clazz);
296+
}
297+
298+
/**
299+
* 将字符串反序列化为原对象,先使用 Base64 解码
300+
*
301+
* @param str {@link #writeToString} 方法序列化后的字符串
302+
* @param clazz 原对象的类型
303+
* @param <T> 原对象的类型
304+
* @return 原对象
305+
*/
306+
public static <T> T readFromString(String str, Class<T> clazz) {
307+
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
308+
return readFromBytes(Base64.getDecoder().decode(bytes), clazz);
309+
}
310+
311+
}
312+
```
313+
314+
测试:
315+
316+
```java
317+
long begin = System.currentTimeMillis();
318+
for (int i = 0; i < BATCH_SIZE; i++) {
319+
TestBean oldBean = BeanUtils.initJdk8Bean();
320+
byte[] bytes = KryoDemo.writeToBytes(oldBean);
321+
TestBean newBean = KryoDemo.readFromBytes(bytes, TestBean.class);
322+
}
323+
long end = System.currentTimeMillis();
324+
System.out.printf("Kryo 序列化/反序列化耗时:%s", (end - begin));
325+
```
141326

142327
## 参考资料
143328

0 commit comments

Comments
 (0)