Hessian序列化示例

发表时间:2017-10-27 10:29:36 浏览量( 19 ) 留言数( 0 )

学习目标:

1、了解Hessian的序列化

2、自己实现一个序列化


学习过程:

这节课我们使用Hessian的方式取代原生的java序列化的方式,

显示Hessian的序列化,代码如下:

public class HessianSerializer  {

	public static <T> byte[] serialize(T obj) {
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		HessianOutput output=new HessianOutput(byteArrayOutputStream);
		try {
			output.writeObject(obj);
			return byteArrayOutputStream.toByteArray();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}

	public static <T> T deserialize(byte[] data) {
		
		ByteArrayInputStream byteArrayinputStream = new ByteArrayInputStream(data);
		
		HessianInput input=new HessianInput(byteArrayinputStream);
		
		try {
			return (T)input.readObject();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}

}

实现编码器,我们不再使用LengthFieldBasedFrameDecoder,而是自己实现这部分的逻辑,在前面使用一个整型数据,也就是4位字节写入内容的长度。代码如下:

public class MyEncoder extends MessageToByteEncoder<Object> {
    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
    	System.out.println("encode");
        try {
            byte[] body = HessianSerializer.serialize(msg);  //将对象转换为byte.
            int dataLength = body.length;  //读取消息的长度
            out.writeInt(dataLength);  //先将消息长度写入,也就是消息头
            out.writeBytes(body);  //消息体中包含我们要发送的数据
        } catch (Exception e) {
            System.out.println(e + "");
        }
    }
}

实现解码器我们也不再使用LengthFieldBasedFrameDecoder,也是自己实现这个逻辑。

public class MyDecord extends ByteToMessageDecoder {
	
	public static final int  HEAD_LENGTH=4;
	
	public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        if (in.readableBytes() < HEAD_LENGTH) {  //这个HEAD_LENGTH是我们用于表示头长度的字节数。  由于上面我们传的是一个int类型的值,所以这里HEAD_LENGTH的值为4.
            return;
        }
        in.markReaderIndex();                  //我们标记一下当前的readIndex的位置
        int dataLength = in.readInt();       // 读取传送过来的消息的长度。ByteBuf 的readInt()方法会让他的readIndex增加4
        if (dataLength < 0) { // 我们读到的消息体长度为0,这是不应该出现的情况,这里出现这情况,关闭连接。
            ctx.close();
        }

        if (in.readableBytes() < dataLength) { //读到的消息体长度如果小于我们传送过来的消息长度,则resetReaderIndex. 这个配合markReaderIndex使用的。把readIndex重置到mark的地方
            in.resetReaderIndex();
            return;
        }

        byte[] body = new byte[dataLength];  //  嗯,这时候,我们读到的长度,满足我们的要求了,把传送过来的数据,取出来吧~~
        in.readBytes(body);  //
        Object o =HessianSerializer.deserialize(body);  //将byte数据转化为我们需要的对象。伪代码,用什么序列化,自行选择
        out.add(o);  
    }

}

修改客户端和服务端的,业务处理的Handler和上一节课一样,就不列出来了,ChannelInitializer的代码如下:

channel.pipeline().addLast(new MyDecord());
channel.pipeline().addLast(new MyEncoder());
channel.pipeline().addLast(new HessianServerHandler());

运行结果一样。


我们也可以把编码器和解码器合并起来。

public class MyCombinedCodec extends CombinedChannelDuplexHandler<MyDecord, MyEncoder> {
	public MyCombinedCodec() {
		super(new MyDecord(), new MyEncoder());
	}

}

修改

//channel.pipeline().addLast(new MyDecord());
//channel.pipeline().addLast(new MyEncoder());
channel.pipeline().addLast(new MyCombinedCodec());
channel.pipeline().addLast(new HessianServerHandler());							

运行结果一样。