Netty学习8-自定义复杂序列化框架

1 概述

《Netty学习7-序列化原理》一文中讲述了序列化的原理,通过Java位运算、JDK原生的NIO、Netty的ChannelBuffer做了序列化操作。本文演示稍微复杂的一个自定义序列化框架,但万变不离其宗,拆解出来还是很简单的。


2 工具类

这是核心类。拆解来看就是调用了ChannelBuffer的readInt和writeInt等方法,并定义了抽象类方法read和write等待实体类实现。

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
/**
 * Buffer工具类
 */
public class BufferUtils {

	/**
	 * 获取一个缓存对象
	 * 
	 * @return 缓存对象
	 */
	public static ChannelBuffer getBuffer() {
		ChannelBuffer dynamicBuffer = ChannelBuffers.dynamicBuffer();
		return dynamicBuffer;
	}

	/**
	 * 将二进制bytes写入缓存对象
	 * 
	 * @param bytes 二进制数据
	 * @return 缓存对象
	 */
	public static ChannelBuffer getBuffer(byte[] bytes) {
		ChannelBuffer copiedBuffer = ChannelBuffers.copiedBuffer(bytes);
		return copiedBuffer;
	}
}

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;
import com.cn.core.BufferFactory;
/**
 * 自定义序列化基类
 */
public abstract class Serializer {

	// 编码对象
	public static final Charset CHARSET = Charset.forName("UTF-8");

	// 写缓存
	protected ChannelBuffer writeBuf;

	// 读缓存
	protected ChannelBuffer readBuf;

	// 反序列化具体实现
	protected abstract void read();

	// 序列化具体实现
	protected abstract void write();

	/***************************************** 序列化 ************************************/

	// 序列化
	public byte[] serialze() {

		// 申明写缓存
		writeBuf = BufferUtils.getBuffer();

		// 将数据写入写缓存
		write();

		// 将写缓存数据读入byte数组
		byte[] bytes = null;
		if (writeBuf.writerIndex() == 0)
			bytes = new byte[0];
		else {
			bytes = new byte[writeBuf.writerIndex()];
			writeBuf.readBytes(bytes);
		}
		writeBuf.clear();
		return bytes;
	}

	public Serializer writeShort(Short value) {
		writeBuf.writeShort(value);
		return this;
	}

	public Serializer writeInt(Integer value) {
		writeBuf.writeInt(value);
		return this;
	}

	public Serializer writeLong(Long value) {
		writeBuf.writeLong(value);
		return this;
	}

	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;
		writeBuf.writeShort(len);
		writeBuf.writeBytes(data);
		return this;
	}

	public Serializer writeByte(Byte value) {
		writeBuf.writeByte(value);
		return this;
	}

	public <T> Serializer writeList(List<T> list) {
		if (isEmpty(list)) {
			writeBuf.writeShort((short) 0);
			return this;
		}
		writeBuf.writeShort((short) list.size());
		for (T item : list) {
			writeObject(item);
		}
		return this;
	}

	public <K, V> Serializer writeMap(Map<K, V> map) {
		if (isEmpty(map)) {
			writeBuf.writeShort((short) 0);
			return this;
		}
		writeBuf.writeShort((short) map.size());
		for (Entry<K, V> entry : map.entrySet()) {
			writeObject(entry.getKey());
			writeObject(entry.getValue());
		}
		return this;
	}

	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.writeToTargetBuffer(writeBuf);
				return this;
			}
			throw new RuntimeException("不可序列化的类型:" + object.getClass());
		}
		return this;
	}

	// 调用对象自身的写入方法
	public ChannelBuffer writeToTargetBuffer(ChannelBuffer buffer) {
		writeBuf = buffer;
		write();
		return writeBuf;
	}

	/***************************************** 反序列化 ************************************/

	public Serializer deserialize(byte[] bytes) {
		readBuf = BufferUtils.getBuffer(bytes);
		read();
		readBuf.clear();
		return this;
	}

	public byte readByte() {
		return readBuf.readByte();
	}

	public short readShort() {
		return readBuf.readShort();
	}

	public int readInt() {
		return readBuf.readInt();
	}

	public long readLong() {
		return readBuf.readLong();
	}

	public String readString() {
		int size = readBuf.readShort();
		if (size <= 0) {
			return "";
		}

		byte[] bytes = new byte[size];
		readBuf.readBytes(bytes);

		return new String(bytes, CHARSET);
	}

	public <T> List<T> readList(Class<T> clz) {
		List<T> list = new ArrayList<>();
		int size = readBuf.readShort();
		for (int i = 0; i < size; i++) {
			list.add(read(clz));
		}
		return list;
	}

	public <K, V> Map<K, V> readMap(Class<K> keyClz, Class<V> valueClz) {
		Map<K, V> map = new HashMap<>();
		int size = readBuf.readShort();
		for (int i = 0; i < size; i++) {
			K key = read(keyClz);
			V value = read(valueClz);
			map.put(key, value);
		}
		return map;
	}

	@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 == String.class) {
			t = readString();
		} else if (Serializer.class.isAssignableFrom(clz)) {
			try {
				byte hasObject = this.readBuf.readByte();
				if (hasObject == 1) {
					Serializer temp = (Serializer) clz.newInstance();
					temp.readFromBuffer(this.readBuf);
					t = temp;
				} else {
					t = null;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}

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

	// 调用对象自身的读取方法
	public void readFromBuffer(ChannelBuffer readBuffer) {
		this.readBuf = readBuffer;
		read();
	}

	/***************************************** 工具方法 ************************************/

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

3 实体类

public class Hobby extends Serializer {

	private String name;

	public Hobby() {

	}

	@Override
	protected void read() {
		this.name = readString();
	}

	@Override
	protected void write() {
		writeString(name);
	}

	public Hobby(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

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

	@Override
	public String toString() {
		return "Hobby [name=" + name + "]";
	}
}

public class Student extends Serializer {

	// 学号
	private Integer id;
	// 姓名
	private String name;
	// 分数
	private Long mark;
	// 同学名
	private List<String> classmates;
	// 爱好
	private List<Hobby> hobbies;
	// 住址
	private Map<String, String> address;

	@Override
	protected void write() {
		writeInt(id);
		writeString(name);
		writeLong(mark);
		writeList(classmates);
		writeList(hobbies);
		writeMap(address);
	}

	@Override
	protected void read() {
		this.id = readInt();
		this.name = readString();
		this.mark = readLong();
		this.classmates = readList(String.class);
		this.hobbies = readList(Hobby.class);
		this.address = readMap(String.class, String.class);
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public Long getMark() {
		return mark;
	}

	public void setMark(Long mark) {
		this.mark = mark;
	}

	public String getName() {
		return name;
	}

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

	public List<String> getClassmates() {
		return classmates;
	}

	public void setClassmates(List<String> classmates) {
		this.classmates = classmates;
	}

	public List<Hobby> getHobbies() {
		return hobbies;
	}

	public void setHobbies(List<Hobby> hobbies) {
		this.hobbies = hobbies;
	}

	public Map<String, String> getAddress() {
		return address;
	}

	public void setAddresses(Map<String, String> address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", mark=" + mark
				+ ", classmates=" + classmates + ", hobbies=" + hobbies
				+ ", address=" + address + "]";
	}
}

4 测试方法

public class XYTest {
	public static void main(String[] args) {

		// 数据初始化
		Student student = new Student();
		student.setId(10);
		student.setName("xy");
		student.setMark(100L);
		List<String> classmates = new ArrayList<String>();
		classmates.add("xiaoming");
		classmates.add("xiaohong");
		student.setClassmates(classmates);
		List<Hobby> hobbies = new ArrayList<Hobby>();
		hobbies.add(new Hobby("football"));
		student.setHobbies(hobbies);
		Map<String, String> address = new HashMap<String, String>();
		address.put("aaa", "bbb");
		address.put("ccc", "ddd");
		student.setAddresses(address);

		// 序列化
		byte[] array = student.serialze();
		System.out.println(Arrays.toString(array));

		// 反序列化
		Student s = new Student();
		s.deserialize(array);
		System.out.println(s.toString());
	}
}

发布了535 篇原创文章 · 获赞 1162 · 访问量 450万+

猜你喜欢

转载自blog.csdn.net/woshixuye/article/details/54134543