Hessian序列化对象之BasicSerializer(五)
来源:互联网 发布:dcp打包软件 编辑:程序博客网 时间:2024/06/02 02:18
在Hessian中所有的序列化对象和反序列化对象都是成对存在的,在接下来分析Hessian序列化对象的博客中,会成对分析,例如本篇分析BasicSerializer的同时也会分析BasicDeserializer
在Hessian中8个基本类型的序列化
boolean,byte,short,int,long,float,double,char
8个基本类型对应的包装类的序列化
Boolean,Byte,Short,Integer,Long,Float,Double,Character
8种基本类型对应的数组
boolean[],byte[],short[],int[],long[],float[],double[],char[]
还有
void,String,Date,String[],Number
上述类型的序列化功能都是由BasicSerializer实现的
Hessian是在ContextSerializerFactory中来初始化上述类对象和序列化对象的对应关系的我们来看一下Hessian是如何做的
ContextSerializerFactory的静态初始化块如下(代码太长,只展示了int类型对应的序列化对象,其余因为篇幅原因省略了)
static { _staticSerializerMap = new HashMap(); _staticDeserializerMap = new HashMap(); _staticClassNameMap = new HashMap(); addBasic(void.class, "void", BasicSerializer.NULL); addBasic(Integer.class, "int", BasicSerializer.INTEGER); addBasic(int.class, "int", BasicSerializer.INTEGER); addBasic(int[].class, "[int", BasicSerializer.INTEGER_ARRAY); // hessian/3bb5 _staticDeserializerMap.put(StackTraceElement.class.getName(), new StackTraceElementDeserializer()); ClassLoader systemClassLoader = null; try { systemClassLoader = ClassLoader.getSystemClassLoader(); } catch (Exception e) { } _systemClassLoader = systemClassLoader; }在静态初始化块中调用静态方法addBasic()来初始化对应关系,addBasic代码如下,类的基本名称和序列化对象的关系被放到了_staticSerializerMap中(注意调用int的getName方法的返回值为int,而调用Integer方法的返回值为java.lang.Integer,这两者是不一样的),而_staticDeserializerMap和_staticClassNameMap是反序列化相关的,
后面博客讲到反序列化时再详细说明
private static void addBasic(Class cl, String typeName, int type) { _staticSerializerMap.put(cl.getName(), new BasicSerializer(type)); Deserializer deserializer = new BasicDeserializer(type); _staticDeserializerMap.put(cl.getName(), deserializer); _staticClassNameMap.put(typeName, deserializer); }这里虽然存放了类和序列化对象的对应关系,但是根据类名获取序列化对象的方法是从_serializerClassMap中拿的,而不是_staticSerializerMap,代码如下
public Serializer getSerializer(String className) { Serializer serializer = _serializerClassMap.get(className); if (serializer == AbstractSerializer.NULL) return null; else return serializer; }这是因为在创建ContextSerializerFactory对象时调用了它的init(),在init()方法中将_staticSerializerMap中的内容复制到了_serializerClassMap中
====================
到此为止通过类名已经拿到了对应的序列化对象,这时会调用writeObject()方法真正的将对象写出到流中,让我们看看BasicObject的writeObject()方法是如何实现的(截取部分代码)
public void writeObject(Object obj, AbstractHessianOutput out) throws IOException { switch (_code) { case BYTE: case SHORT: case INTEGER: out.writeInt(((Number) obj).intValue()); break; case STRING: out.writeString((String) obj); break; case STRING_BUILDER: out.writeString(((StringBuilder) obj).toString()); break; case DATE: out.writeUTCDate(((Date) obj).getTime()); break; case INTEGER_ARRAY: { if (out.addRef(obj)) return; int []data = (int []) obj; boolean hasEnd = out.writeListBegin(data.length, "[int"); for (int i = 0; i < data.length; i++) out.writeInt(data[i]); if (hasEnd) out.writeListEnd(); break; } case CHARACTER_ARRAY: { char []data = (char []) obj; out.writeString(data, 0, data.length); break; } case OBJECT_ARRAY: { if (out.addRef(obj)) return; Object []data = (Object []) obj; boolean hasEnd = out.writeListBegin(data.length, "[object"); for (int i = 0; i < data.length; i++) { out.writeObject(data[i]); } if (hasEnd) out.writeListEnd(); break; } case NULL: out.writeNull(); break; case OBJECT: ObjectHandleSerializer.SER.writeObject(obj, out); break; case BYTE_HANDLE: out.writeObject(new ByteHandle((Byte) obj)); break; case SHORT_HANDLE: out.writeObject(new ShortHandle((Short) obj)); break; case FLOAT_HANDLE: out.writeObject(new FloatHandle((Float) obj)); break; default: throw new RuntimeException(_code + " unknown code for " + obj.getClass()); } }实际上BasicSerializer是调用了HessianOutput的write***()方法将信息写出到流中的,具体代码如下
向流中写一个int类型的变量
public void writeInt(int value) throws IOException { os.write('I'); os.write(value >> 24); os.write(value >> 16); os.write(value >> 8); os.write(value); }
其余的write***()方法就不一一展示了,有兴趣的同学可以去GitHub上下载Hessian的源码看一下HessianOutput类具体是如何实现的
当把服务端收到客户端序列化过来的对象后会进行反序列化,下面来看一下BasicDeserializer的readObject()方法是如何实现的,可以看到反序列化调用的是AbstractHessianInput的实现类HessianInput的方法来实现的
public Object readObject(AbstractHessianInput in) throws IOException { switch (_code) { case NULL: // hessian/3490 in.readObject(); return null; case BOOLEAN: return Boolean.valueOf(in.readBoolean()); case BYTE: return Byte.valueOf((byte) in.readInt()); case SHORT: return Short.valueOf((short) in.readInt()); case INTEGER: return Integer.valueOf(in.readInt()); case LONG: return Long.valueOf(in.readLong()); case FLOAT: return Float.valueOf((float) in.readDouble()); case DOUBLE: return Double.valueOf(in.readDouble()); case STRING: return in.readString(); case OBJECT: return in.readObject(); case CHARACTER: { String s = in.readString(); if (s == null || s.equals("")) return Character.valueOf((char) 0); else return Character.valueOf(s.charAt(0)); } case CHARACTER_OBJECT: { String s = in.readString(); if (s == null || s.equals("")) return null; else return Character.valueOf(s.charAt(0)); } case DATE: return new Date(in.readUTCDate()); case NUMBER: return in.readObject(); case BYTE_ARRAY: return in.readBytes(); case CHARACTER_ARRAY: { String s = in.readString(); if (s == null) return null; else { int len = s.length(); char []chars = new char[len]; s.getChars(0, len, chars, 0); return chars; } } case BOOLEAN_ARRAY: case SHORT_ARRAY: case INTEGER_ARRAY: case LONG_ARRAY: case FLOAT_ARRAY: case DOUBLE_ARRAY: case STRING_ARRAY: { int code = in.readListStart(); switch (code) { case 'N': return null; case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: int length = code - 0x10; in.readInt(); return readLengthList(in, length); default: String type = in.readType(); length = in.readLength(); return readList(in, length); } } default: throw new UnsupportedOperationException(); } }
下面这段代码就是HessianInput类的readInt方法,可以看到先从流中读取了一个字节,通过该字节来判断接下来的变量是boolean类型的还是int类型还是其他类型
public int readInt() throws IOException { int tag = read(); switch (tag) { case 'T': return 1; case 'F': return 0; case 'I': return parseInt(); case 'L': return (int) parseLong(); case 'D': return (int) parseDouble(); default: throw expect("int", tag); } }
思考一个问题
为什么要把写基本类型到流中的实现比如writeInt()方法在HessianOutput中实现而不是在BasicSerializer中实现呢?
- Hessian序列化对象之BasicSerializer(五)
- Hessian序列化对象之CollectionSerializer(六)
- hessian序列化
- hessian序列化区别
- Hessian序列化详解
- Hessian RPC示例和基于Http请求的Hessian序列化对象传输
- Lucene 实现 hessian序列化
- hessian 序列化实现 初探
- Hessian 序列化,反序列
- 序列化框架性能对比(kryo、hessian、java、protostuff)
- java序列化框架性能对比(kryo,hessian,Protostuff)
- hessian序列化反序列化util
- Hessian远程调用及序列化协议
- Hessian远程调用及序列化协议
- Kryo与Hessian的序列化比较
- Hessian 2.0序列化协议规范
- Hessian 2.0序列化协议规范
- hessian原理解析三(序列化协议)
- AOP
- php之PDO (PHP DATA OBJECT)
- Bluetooth MESH探究 --- (1)
- apache-comnons系列之commons-dbutils1.7 学习笔记
- eclipse 编辑窗口不见了(打开左边的java、xml文件,中间不会显示代码)
- Hessian序列化对象之BasicSerializer(五)
- Python 爬虫 工具 列表
- Python——程序入口main函数
- 30最棒的响应式css前端框架
- 图论小结
- 牛客网编程基础1-5
- 53. Maximum Subarray
- 《一个Android工程的从零开始》-8、base(七) Retrofit的封装
- 编译安装tcpdump