Netty自定义序列化协议

自定义序列化协议

序列化的目的就是想对象转化成字节数组byteArray

阶段一
使用流的形式

public class Test{
public static void main(String[] args) throws IOException {
		int id = 100;
		int age = 22;
		ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
		arrayOutputStream.write(int2bytes(id));//序列化
		arrayOutputStream.write(int2bytes(age));	
		byte[] byteArray = arrayOutputStream.toByteArray();
		//==================通过socket传输字节序列=================================
		ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(byteArray);
		byte[] idBytes = new byte[4];//读取4个字节
		arrayInputStream.read(idBytes);
	        System.out.println("id:" + bytes2int(idBytes));//反序列化
		byte[] ageBytes = new byte[4];
		arrayInputStream.read(ageBytes);
		System.out.println("age:" + bytes2int(ageBytes));		
	}
	
/*
* int 类型占4个字节  采用大端字节序列(高位在前面)
*/
//序列化
public static byte[] int2byte(int i)
{
    byte[]bytes =new byte[4];
    bytes[0]=(byte)(i >> 3*8);
    bytes[1]=(byte)(i >> 2*8);
    bytes[2]=(byte)(i >> 1*8);
   bytes[3]=(byte)(i >> 0*8);
   return bytes;
}
//反序列化
pulic static int byte2int(byte[]bytes)
{
   return (bytes[0] << 3*8) |
				(bytes[1] << 2*8) |
				(bytes[2] << 1*8) |
				(bytes[3] << 0*8);}
}

阶段二
使用byteBuff 完成序列化部分

  • 可以对多种类型进行序列化、反序列化操作
  • byteBuff要声明大小,且不能自动拓展
  • ****OutputStream、***InputStream具有自动扩容的方法
 public static void main(String[] args) throws IOException {
		
            int id = 100;
		    nt age = 22;			
  	        ByteBuffer buffer = ByteBuffer.allocate(8);
            buffer.putInt(id);
            buffer.putInt(age);
	    	byte[] byteArray = buffer.array();
		//==================通过socket传输字节序列=================================   	
           ByteBuffer buffer2 = ByteBuffer.wrap(array);
	       System.out.println("id:"+buffer2.getInt());
		  System.out.println("age:"+buffer2.getInt());

阶段三
使用Netty ChannelBuffer

  • 可以自动扩容,并且可以对多种整型数据类型进行序列化、反序列化操作
  • 不能对操作String
	public static void main(String[] args) {

		ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
		buffer.writeInt(101);
		buffer.writeDouble(80.1);
		byte[] bytes = new byte[buffer.writerIndex()];
		buffer.readBytes(bytes);
		System.out.println(Arrays.toString(bytes));
		"abc".getBytes();	
		//================================================
		ChannelBuffer wrappedBuffer = ChannelBuffers.wrappedBuffer(bytes);
		System.out.println(wrappedBuffer.readInt());
		System.out.println(wrappedBuffer.readDouble());
		
	}

阶段四
Netty ChannelBuffer对进行集成处理

  • 在阶段三的基础上支持String、List等数据类型
  • 实现对类对象的序列化
  • 继承Serializer抽象类(借助Netty自定义的序列化规则)
  • 重写read()、write()时属性顺序要一致
  • 如果属性是对象的话(如,Resource),同样也要继承Serializer抽象类
public class Player extends Serializer{
	
	private long playerId;
	
	private int age;
	
	private List<Integer> skills = new ArrayList<>();
	
	private Resource resource = new Resource();
	
	public Resource getResource() {
		return resource;
	}

	public void setResource(Resource resource) {
		this.resource = resource;
	}

	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 List<Integer> getSkills() {
		return skills;
	}

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

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

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

使用案例

  • Player、Resource对象继承了Serializer抽象类
  • 序列化:player.getBytes()
  • 反序列:player2.readFromBytes(bytes)
    public static void main(String[] args) {
    		Player player = new Player();
    		player.setPlayerId(10001);
    		player.setAge(22);
    		player.getSkills().add(101);
    		player.getResource().setGold(99999);	
    		byte[] bytes = player.getBytes();//内部调用write()进行序列化		
    		System.out.println(Arrays.toString(bytes));
    		//==============================================
    		Player player2 = new Player();
    		player2.readFromBytes(bytes);//内部调用read()进行反序列化
    		System.out.println(player2.getPlayerId() + "   "+player2.getAge() + "     "+ Arrays.toString(player2.getSkills().toArray())+"   " +player2.getResource().getGold());
    
    	}
  • 阶段5

Protocol Buff 对阶段四的进一步优化

  • 在客户端和服务器都配置序列化配置文件
  • ProtocolBuff内部通过位运算,可以避免Java本身数据类型新建造成空间的浪费,从而更加高效的完成序列化
//序列化
public static byte[] toBytes() throws IOException{
//获取一个user的构造器
Builder builder =PlayerModule.user.newBuidler();
//设置数据
builder.setId(10).setAge(18).setName("luo").addSkills(1001);
//构造对象
User user =builder.build();
//序列化成字节数组
byte[] byteArray= user.toByteArray();
return byteArray;
}


//反序列化
public static void toPlayer(byte[] bs) throws Exception{
		
		ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(bs));
		User player = (User)inputStream.readObject();	
		//打印
		 System.out.println("Id:" + player.getPlayerId());
		 System.out.println("age:" + player.getAge());
		 System.out.println("name:" + player.getName());
		 System.out.println("skills:" + (Arrays.toString(player.getSkills().toArray())));
	}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值