hessian——序列化
当方法返回的类型未implement java.io.Serializable时,会throw exception;
原因: SerializerFactory中以下方法:
/**
* Returns the default serializer for a class that isn't matched
* directly. Application can override this method to produce
* bean-style serialization instead of field serialization.
*
* @param cl the class of the object that needs to be serialized.
*
* @return a serializer object for the serialization.
*/
protected Serializer getDefaultSerializer(Class cl)
{
if (_defaultSerializer != null)
return _defaultSerializer;
if (! Serializable.class.isAssignableFrom(cl)
&& ! _isAllowNonSerializable) {
throw new IllegalStateException("Serialized class " + cl.getName() + " must implement java.io.Serializable");
}
if (_isEnableUnsafeSerializer
&& JavaSerializer.getWriteReplace(cl) == null) {
return UnsafeSerializer.create(cl);
}
else
return JavaSerializer.create(cl);
}
其中_isAllowNonSerializable默认为false。那如果返回的类型不想implement java.io.Serializable 怎么办呢?
查看HessianServlet中的代码,没有修改SerializerFactory的_isAllowNonSerializable的值,也就是不能通过web.xml中的配置来设置这个开关了,所以只能使用自己继承HessianServlet的servlet了,然后在自定义的servlet中把SerializerFactory的_isAllowNonSerializable值改为true;
public boolean isAllowNonSerializable()
{
return _isAllowNonSerializable;
}
再看看isAllowNonSerializable()被调用的情况,发现没有被任何对象调用,说明_isAllowNonSerializable只会在getDefaultSerializer()方法中起作用,也从另一方面说明hessian的序列化跟java.io.Serializable无关,只是有个_isAllowNonSerializable的开关而已,hessian实现了自己的***方式:
Hessian2Output.java:
/**
* Writes any object to the output stream.
*/
public void writeObject(Object object)
throws IOException
{
if (object == null) {
writeNull();
return;
}
Serializer serializer
= findSerializerFactory().getObjectSerializer(object.getClass());
serializer.writeObject(object, this);
}
UnsafeSerializer.java:
public void writeObject(Object obj, AbstractHessianOutput out)
throws IOException
{
if (out.addRef(obj)) {
return;
}
Class<?> cl = obj.getClass();
int ref = out.writeObjectBegin(cl.getName());
if (ref >= 0) {
writeInstance(obj, out);
}
else if (ref == -1) {
writeDefinition20(out);
out.writeObjectBegin(cl.getName());
writeInstance(obj, out);
}
else {
writeObject10(obj, out);
}
}
final public void writeInstance(Object obj, AbstractHessianOutput out)
throws IOException
{
try {
FieldSerializer []fieldSerializers = _fieldSerializers;
int length = fieldSerializers.length;
for (int i = 0; i < length; i++) {
fieldSerializers[i].serialize(out, obj); //序列化方法返回结果到输出流
}
} catch (RuntimeException e) {
throw new RuntimeException(e.getMessage() + "\n class: "
+ obj.getClass().getName()
+ " (object=" + obj + ")",
e);
} catch (IOException e) {
throw new IOExceptionWrapper(e.getMessage() + "\n class: "
+ obj.getClass().getName()
+ " (object=" + obj + ")",
e);
}
}
@Override
final void serialize(AbstractHessianOutput out, Object obj)
throws IOException
{
try {
Object value = _unsafe.getObject(obj, _offset); //获取obj对象中的属性值
out.writeObject(value);//把属性值写入out,由于属性值是基本类型(比如:字符串),则writeObject会调用字符串相应的serializer(BasicSerializer)的serialize(out, obj)方法(见后面)
} catch (RuntimeException e) {
throw new RuntimeException(e.getMessage() + "\n field: "
+ _field.getDeclaringClass().getName()
+ '.' + _field.getName(),
e);
} catch (IOException e) {
throw new IOExceptionWrapper(e.getMessage() + "\n field: "
+ _field.getDeclaringClass().getName()
+ '.' + _field.getName(),
e);
}
}
基本类型对应的BasicSerializer的serializer(out,obj)方法:
public void writeObject(Object obj, AbstractHessianOutput out)
throws IOException
{
switch (_code) {
case BOOLEAN:
out.writeBoolean(((Boolean) obj).booleanValue());
break;
case BYTE:
case SHORT:
case INTEGER:
out.writeInt(((Number) obj).intValue());
break;
case LONG:
out.writeLong(((Number) obj).longValue());
break;
case FLOAT:
case DOUBLE:
out.writeDouble(((Number) obj).doubleValue());
break;
case CHARACTER:
case CHARACTER_OBJECT:
out.writeString(String.valueOf(obj));
break;
case STRING:
out.writeString((String) obj);
break;
case DATE:
out.writeUTCDate(((Date) obj).getTime());
break;
case BOOLEAN_ARRAY:
{
if (out.addRef(obj))
return;
boolean []data = (boolean []) obj;
boolean hasEnd = out.writeListBegin(data.length, "[boolean");
for (int i = 0; i < data.length; i++)
out.writeBoolean(data[i]);
if (hasEnd)
out.writeListEnd();
break;
}
case BYTE_ARRAY:
{
byte []data = (byte []) obj;
out.writeBytes(data, 0, data.length);
break;
}
case SHORT_ARRAY:
{
if (out.addRef(obj))
return;
short []data = (short []) obj;
boolean hasEnd = out.writeListBegin(data.length, "[short");
for (int i = 0; i < data.length; i++)
out.writeInt(data[i]);
if (hasEnd)
out.writeListEnd();
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 LONG_ARRAY:
{
if (out.addRef(obj))
return;
long []data = (long []) obj;
boolean hasEnd = out.writeListBegin(data.length, "[long");
for (int i = 0; i < data.length; i++)
out.writeLong(data[i]);
if (hasEnd)
out.writeListEnd();
break;
}
case FLOAT_ARRAY:
{
if (out.addRef(obj))
return;
float []data = (float []) obj;
boolean hasEnd = out.writeListBegin(data.length, "[float");
for (int i = 0; i < data.length; i++)
out.writeDouble(data[i]);
if (hasEnd)
out.writeListEnd();
break;
}
case DOUBLE_ARRAY:
{
if (out.addRef(obj))
return;
double []data = (double []) obj;
boolean hasEnd = out.writeListBegin(data.length, "[double");
for (int i = 0; i < data.length; i++)
out.writeDouble(data[i]);
if (hasEnd)
out.writeListEnd();
break;
}
case STRING_ARRAY:
{
if (out.addRef(obj))
return;
String []data = (String []) obj;
boolean hasEnd = out.writeListBegin(data.length, "[string");
for (int i = 0; i < data.length; i++) {
out.writeString(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());
}
}
再看看out怎么写基本类型的:
public void writeBoolean(boolean value)
throws IOException
{
if (SIZE < _offset + 16)
flushBuffer();
if (value)
_buffer[_offset++] = (byte) 'T';
else
_buffer[_offset++] = (byte) 'F';
}
public void writeInt(int value)
throws IOException
{
int offset = _offset;
byte []buffer = _buffer;
if (SIZE <= offset + 16) {
flushBuffer();
offset = _offset;
}
if (INT_DIRECT_MIN <= value && value <= INT_DIRECT_MAX)
buffer[offset++] = (byte) (value + BC_INT_ZERO);
else if (INT_BYTE_MIN <= value && value <= INT_BYTE_MAX) {
buffer[offset++] = (byte) (BC_INT_BYTE_ZERO + (value >> 8));
buffer[offset++] = (byte) (value);
}
else if (INT_SHORT_MIN <= value && value <= INT_SHORT_MAX) {
buffer[offset++] = (byte) (BC_INT_SHORT_ZERO + (value >> 16));
buffer[offset++] = (byte) (value >> 8);
buffer[offset++] = (byte) (value);
}
else {
buffer[offset++] = (byte) ('I');
buffer[offset++] = (byte) (value >> 24);
buffer[offset++] = (byte) (value >> 16);
buffer[offset++] = (byte) (value >> 8);
buffer[offset++] = (byte) (value);
}
_offset = offset;
}
public final void flushBuffer()
throws IOException
{
int offset = _offset;
OutputStream os = _os;
if (! _isPacket && offset > 0) {
_offset = 0;
if (os != null)
os.write(_buffer, 0, offset);
}
else if (_isPacket && offset > 3) {
int len = offset - 3;
_buffer[0] = (byte) 0x80;
_buffer[1] = (byte) (0x80 + ((len >> 7) & 0x7f));
_buffer[2] = (byte) (len & 0x7f);
_offset = 3;
if (os != null)
os.write(_buffer, 0, offset);
_buffer[0] = (byte) 0x56;
_buffer[1] = (byte) 0x56;
_buffer[2] = (byte) 0x56;
}
}
public final static int SIZE = 4096;
可见项buffer中写数据前,都会判断_offset大写,如果足够大,则flushBuffer。
上一篇: python os