文章目录
  1. 1、协议实现方式说明
  2. 2、具体实现

1、协议实现方式说明

  1. 序列化
    • 使用netty3中的ChannelBuffers类提供的dynamicBuffer()方法创建动态长度可变的ChannelBuffer,用于存储序列化后的字节数组
    • 对于基本类型(byte、short、int、long、double、float、double),使用ChannelBuffer的writeXxx方法写入
    • 对于String类型数据,采用short+Byte[]的格式写入,其中short表示String转成byte数组后数组的长度
    • 对于List类型数据,采用short+Object+Object...格式写入,其中short表示list中元素的个数,Object为List中的元素
    • 对于Map类型数据,采用short+KeyObject+ValueObject+KeyObject+ValueObject...格式写入,其中short表示map中元素的个数
    • 对于其他类型数据,需继承一个基类,继承该基类的类需提供写入方法的具体实现
  2. 反序列化
    • 使用netty3中的ChannelBuffers类提供的copiedBuffer(byte[] array)方法创建ChannelBuffer对象,通过该ChannelBuffer对象来读取属性值
    • 对于基本类型(byte、short、int、long、double、float、double),使用ChannelBuffer的readXxx方法读取
    • 对于String类型数据,先读取short即字符串字节数组长度size,再通过size读取字符串
    • 对于List类型的数据,先读取short即List中元素个数,再循环读取信息加入到List中
    • 对于Map类型的数据,先读取short即Map中元素个数,再循环读取key值和value值加入到Map中
    • 对于其他数据类型,需继承一个基类,继承该基类的类需提供读取方法的具体实现

2、具体实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package io.github.lin38.serialize.demo007;


import java.nio.ByteOrder;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
/**
* buff工厂
*/
public class BufferFactory {

// 大端序列
public static ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN;

/**
* 获取一个buffer
*/
public static ChannelBuffer getBuffer() {
ChannelBuffer dynamicBuffer = ChannelBuffers.dynamicBuffer();
return dynamicBuffer;
}

/**
* 将数据写入buffer
*/
public static ChannelBuffer getBuffer(byte[] bytes) {
ChannelBuffer copiedBuffer = ChannelBuffers.copiedBuffer(bytes);
return copiedBuffer;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
package io.github.lin38.serialize.demo007;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.jboss.netty.buffer.ChannelBuffer;

/**
* 自定义序列化接口
*/
public abstract class Serializer {

// 采用UTF-8的字符集
public static final Charset CHARSET = Charset.forName("UTF-8");

// 用于写-序列化
protected ChannelBuffer writeBuffer;

// 用于读-反序列化
protected ChannelBuffer readBuffer;

/**
* 反序列化具体实现,交给子类实现
*/
protected abstract void read();

/**
* 序列化具体实现,交给子类实现
*/
protected abstract void write();

/**
* 反序列化,从byte数组获取数据
*/
public Serializer readFromBytes(byte[] bytes) {
readBuffer = BufferFactory.getBuffer(bytes);
read();
readBuffer.clear();
return this;
}

/**
* 从buff获取数据
*/
public void readFromBuffer(ChannelBuffer readBuffer) {
this.readBuffer = readBuffer;
read();
}

/**
* 写入本地buff
*/
public ChannelBuffer writeToLocalBuff() {
writeBuffer = BufferFactory.getBuffer();
write();
return writeBuffer;
}

/**
* 写入目标buff
*/
public ChannelBuffer writeToTargetBuff(ChannelBuffer buffer) {
writeBuffer = buffer;
write();
return writeBuffer;
}

/**
* 序列化,返回buffer数组
*/
public byte[] getBytes() {
writeToLocalBuff();
byte[] bytes = null; // 待返回数组
if (writeBuffer.writerIndex() == 0) { // 如果写索引值为0,即无数据写入
bytes = new byte[0];
} else {
bytes = new byte[writeBuffer.writerIndex()]; // 创建一个与写索引值相同的数组用于存储序列化数据
writeBuffer.readBytes(bytes);
}
writeBuffer.clear();
return bytes;
}

/**
* 反序列化时,读取一个byte类型的字段值
*/
public byte readByte() {
return readBuffer.readByte();
}

/**
* 反序列化时,读取一个short类型的字段值
*/
public short readShort() {
return readBuffer.readShort();
}

/**
* 反序列化时,读取一个int类型的字段值
*/
public int readInt() {
return readBuffer.readInt();
}

/**
* 反序列化时,读取一个long类型的字段值
*/
public long readLong() {
return readBuffer.readLong();
}

/**
* 反序列化时,读取一个float类型的字段值
*/
public float readFloat() {
return readBuffer.readFloat();
}

/**
* 反序列化时,读取一个double类型的字段值
*/
public double readDouble() {
return readBuffer.readDouble();
}

/**
* 反序列化时,读取一个String类型的字段值
*/
public String readString() {
int size = readBuffer.readShort(); // 获取字符串对应byte数组长度
if (size <= 0) {
return "";
}

byte[] bytes = new byte[size]; // 创建等容量的数组用于存储数据
readBuffer.readBytes(bytes);

return new String(bytes, CHARSET);
}

/**
* 反序列化时,读取一个List类型的字段值
*/
public <T> List<T> readList(Class<T> clz) {
List<T> list = new ArrayList<>();
int size = readBuffer.readShort(); // 获取list内存储对象的个数
for (int i = 0; i < size; i++) { // 循环加入元素
list.add(read(clz)); // 获取clz类型的元素内容
}
return list;
}

/**
* 反序列化时,读取一个Map类型的字段值
*/
public <K, V> Map<K, V> readMap(Class<K> keyClz, Class<V> valueClz) { // key的类型,value的类型
Map<K, V> map = new HashMap<>();
int size = readBuffer.readShort(); // 获取map内存储对象的个数
for (int i = 0; i < size; i++) { // 循环加入元素
K key = read(keyClz); // 获取key
V value = read(valueClz); // 获取value
map.put(key, value);
}
return map;
}

/**
* 反序列化时,读取一个给定class类型的字段值
*/
@SuppressWarnings("unchecked")
public <I> I read(Class<I> clz) {
Object t = null;
if (clz == int.class || clz == Integer.class) {
t = this.readInt();
} else if (clz == byte.class || clz == Byte.class) {
t = this.readByte();
} else if (clz == short.class || clz == Short.class) {
t = this.readShort();
} else if (clz == long.class || clz == Long.class) {
t = this.readLong();
} else if (clz == float.class || clz == Float.class) {
t = readFloat();
} else if (clz == double.class || clz == Double.class) {
t = readDouble();
} else if (clz == String.class) {
t = readString();
} else if (Serializer.class.isAssignableFrom(clz)) { // 是否是Serializer的子类
try {
byte hasObject = this.readBuffer.readByte();
if (hasObject == 1) {
Serializer temp = (Serializer) clz.newInstance();
temp.readFromBuffer(this.readBuffer);
t = temp;
} else {
t = null;
}
} catch (Exception e) {
e.printStackTrace();
}

} else {
throw new RuntimeException(String.format("不支持类型:[%s]", clz));
}
return (I) t;
}

/**
* 序列化时,写入一个byte类型的字段值
*/
public Serializer writeByte(Byte value) {
writeBuffer.writeByte(value);
return this;
}

/**
* 序列化时,写入一个short类型的字段值
*/
public Serializer writeShort(Short value) {
writeBuffer.writeShort(value);
return this;
}

/**
* 序列化时,写入一个int类型的字段值
*/
public Serializer writeInt(Integer value) {
writeBuffer.writeInt(value);
return this;
}

/**
* 序列化时,写入一个long类型的字段值
*/
public Serializer writeLong(Long value) {
writeBuffer.writeLong(value);
return this;
}

/**
* 序列化时,写入一个float类型的字段值
*/
public Serializer writeFloat(Float value) {
writeBuffer.writeFloat(value);
return this;
}

/**
* 序列化时,写入一个double类型的字段值
*/
public Serializer writeDouble(Double value) {
writeBuffer.writeDouble(value);
return this;
}

/**
* 序列化时,写入一个List类型的字段值
* 格式:short+Object+Object...
* short表示list中元素的个数
*/
public <T> Serializer writeList(List<T> list) {
if (isEmpty(list)) {
writeBuffer.writeShort((short) 0);
return this;
}
writeBuffer.writeShort((short) list.size());
for (T item : list) {
writeObject(item);
}
return this;
}

/**
* 序列化时,写入一个Map类型的字段值
* 格式:short+KeyObject+ValueObject+KeyObject+ValueObject...
* short表示map中元素的个数
*/
public <K, V> Serializer writeMap(Map<K, V> map) {
if (isEmpty(map)) {
writeBuffer.writeShort((short) 0);
return this;
}
writeBuffer.writeShort((short) map.size());
for (Entry<K, V> entry : map.entrySet()) {
writeObject(entry.getKey());
writeObject(entry.getValue());
}
return this;
}

/**
* 序列化时,写入一个String类型的字段值
* 格式:short+Byte[]
* short表示String对应byte数组的长度
*/
public Serializer writeString(String value) {
if (value == null || value.isEmpty()) {
writeShort((short) 0);
return this;
}

byte data[] = value.getBytes(CHARSET);
short len = (short) data.length;
writeBuffer.writeShort(len);
writeBuffer.writeBytes(data);
return this;
}

/**
* 序列化时,写入一个Object类型的字段值
*/
public Serializer writeObject(Object object) {

if (object == null) {
writeByte((byte) 0);
} else {

if (object instanceof Integer) {
writeInt((int) object);
return this;
}

if (object instanceof Long) {
writeLong((long) object);
return this;
}

if (object instanceof Short) {
writeShort((short) object);
return this;
}

if (object instanceof Byte) {
writeByte((byte) object);
return this;
}

if (object instanceof String) {
String value = (String) object;
writeString(value);
return this;
}
if (object instanceof Serializer) {
writeByte((byte) 1);
Serializer value = (Serializer) object;
value.writeToTargetBuff(writeBuffer);
return this;
}

throw new RuntimeException("不可序列化的类型:" + object.getClass());
}

return this;
}

private <T> boolean isEmpty(Collection<T> c) {
return c == null || c.size() == 0;
}

public <K, V> boolean isEmpty(Map<K, V> c) {
return c == null || c.size() == 0;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package io.github.lin38.serialize.demo007;

import java.util.ArrayList;
import java.util.List;

/**
* 被序列化对象,继承自定义的Serializer
*/
public class Player extends Serializer {

private long playerId;

private int age;

private String name;

private List<Integer> skills = new ArrayList<>();

public Player() {
}

public Player(long playerId, int age, String name) {
this.playerId = playerId;
this.age = age;
this.name = name;
}

@Override
protected void read() {
this.playerId = readLong();
this.age = readInt();
this.name = readString();
this.skills = readList(Integer.class);
}

@Override
protected void write() {
writeLong(playerId);
writeInt(age);
writeString(name);
writeList(skills);
}

public long getPlayerId() {
return playerId;
}

public void setPlayerId(long playerId) {
this.playerId = playerId;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<Integer> getSkills() {
return skills;
}

public void setSkills(List<Integer> skills) {
this.skills = skills;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package io.github.lin38.serialize.demo007;

import java.io.IOException;
import java.util.Arrays;

/**
* 测试类
*/
public class Serial2Bytes {

public static void main(String[] args) throws Exception {
byte[] bytes = toBytes();
toPlayer(bytes);
}

/**
* 序列化
*/
public static byte[] toBytes() throws IOException {

Player player = new Player(320, 20, "peter");
player.getSkills().add(1001);

// 获取 字节数组
byte[] byteArray = player.getBytes();
System.out.println(Arrays.toString(byteArray));
return byteArray;
}

/**
* 反序列化
*/
public static void toPlayer(byte[] bs) throws Exception {

Player player = new Player();
player.readFromBytes(bs);

// 打印
System.out.println("playerId:" + player.getPlayerId());
System.out.println("age:" + player.getAge());
System.out.println("name:" + player.getName());
System.out.println("skills:" + (Arrays.toString(player.getSkills().toArray())));
}

}

执行结果:

1
2
3
4
5
[0, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 20, 0, 5, 112, 101, 116, 101, 114, 0, 1, 0, 0, 3, -23]
playerId:320
age:20
name:peter
skills:[1001]
文章目录
  1. 1、协议实现方式说明
  2. 2、具体实现