dubbo解耦service层和action层操作model属性问题

在开发中,采用SSM框架,通过dubbo将服务层和action层解耦。多人操作一个实体Model(子),刚好这个Model又继承另一个Model(父),一哥们在不知情的情况下,在子Model中定义了一个父Model已经存在的属性。查询后,发现这一字段的值为null,转化为json输出到前端页面时这一属性直接丢失了。通过debug发现,在service层查询后封装到Model时,数据是存在的,但是一到action层,再向页面返回时,这一属性已经为null了。

针对这一现象,推断如下:

dubbo序列化(在service层) ---->传输 ---->dubbo反序列化(在Action层),应该是在反序列化的过程中把子Model重写的属性给覆盖了。

根据这一推断,去阅读dubbo源码,如下:

com.alibaba.com.caucho.hessian.io.JavaDeserializer  --->反序列化
/**
 * Creates a map of the classes fields.
 */
protected HashMap getFieldMap(Class cl)
{
	HashMap fieldMap = new HashMap();

	for (; cl != null; cl = cl.getSuperclass()) {
		Field []fields = cl.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];

			if (Modifier.isTransient(field.getModifiers())
					|| Modifier.isStatic(field.getModifiers()))
				continue;
			else if (fieldMap.get(field.getName()) != null)   //由子类到父类,子类放入,父类不再放入,Map的key唯一,即属性对应的解析器唯一
				continue;

			// XXX: could parameterize the handler to only deal with public
			try {
				field.setAccessible(true);
			} catch (Throwable e) {
				e.printStackTrace();
			}

			Class type = field.getType();
			FieldDeserializer deser;

			if (String.class.equals(type))
				deser = new StringFieldDeserializer(field);
			else if (byte.class.equals(type)) {
				deser = new ByteFieldDeserializer(field);
			}
			else if (short.class.equals(type)) {
				deser = new ShortFieldDeserializer(field);
			}
			else if (int.class.equals(type)) {
				deser = new IntFieldDeserializer(field);
			}
			else if (long.class.equals(type)) {
				deser = new LongFieldDeserializer(field);
			}
			else if (float.class.equals(type)) {
				deser = new FloatFieldDeserializer(field);
			}
			else if (double.class.equals(type)) {
				deser = new DoubleFieldDeserializer(field);
			}
			else if (boolean.class.equals(type)) {
				deser = new BooleanFieldDeserializer(field);
			}
			else if (java.sql.Date.class.equals(type)) {
				deser = new SqlDateFieldDeserializer(field);
			}
			else if (java.sql.Timestamp.class.equals(type)) {
				deser = new SqlTimestampFieldDeserializer(field);
			}
			else if (java.sql.Time.class.equals(type)) {
				deser = new SqlTimeFieldDeserializer(field);
			}
			else {
				deser = new ObjectFieldDeserializer(field);
			}

			fieldMap.put(field.getName(), deser);
		}
	}

	return fieldMap;
}

上面这段代码是构造解析时的属性解析器。

//com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(AbstractHessianInput, Object, String[])
public Object readObject(AbstractHessianInput in,     //in ----> com.alibaba.com.caucho.hessian.io.Hessian2Input@5513639d
			Object obj,
			String []fieldNames)
					throws IOException
	{
		try {
			int ref = in.addRef(obj);

			for (int i = 0; i < fieldNames.length; i++) {  //遍历所有的fieldName
				String name = fieldNames[i];

				FieldDeserializer deser = (FieldDeserializer) _fieldMap.get(name);//反序列化父类时,拿到反序列化器,但此时父类属性的值为null

				if (deser != null)  //不为null,即存在反序列化器,反序列化属性
					deser.deserialize(in, obj);
				else
					in.readObject();//不识别,直接读取
			}

			Object resolve = resolve(obj);//解析对象

			if (obj != resolve)//不相等,解析成功,返回resolve
				in.setRef(ref, resolve);//重置引用关系

			return resolve;
		} catch (IOException e) {
			throw e;
		} catch (Exception e) {
			throw new IOExceptionWrapper(obj.getClass().getName() + ":" + e, e);
		}
	}

fieldNames是一个String数组,存放子Model的所有属性,包括从父Model继承得到的属性,并且子Model中的属性在数组前面,父Model属性位于数组靠后的元素。这样解析后,利用反射赋值,相当于给实例重新set了父类的属性值,而父类属性值为null,这样就造成了前面提到的问题。

com.alibaba.com.caucho.hessian.io.JavaDeserializer.StringFieldDeserializer
/**
	* 字符串反序列化
	*/
	static class StringFieldDeserializer extends FieldDeserializer {
		private final Field _field;

		StringFieldDeserializer(Field field)
		{
			_field = field;
		}

		void deserialize(AbstractHessianInput in, Object obj)
				throws IOException
		{
			String value = null;

			try {
				value = in.readString();

				_field.set(obj, value);  //利用反射给对象设置属性
			} catch (Exception e) {
				logDeserializeError(_field, obj, value, e);
			}
		}
	}

所以在使用dubbo解耦service层和action层时,操作的实体Model一定注意,子类不要去重写父类的属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值