MSM Session共享实现时 Hibernate持久化对象的Kryo序列化方案。

在用MSM 来共享集群中HttpSession的场景中

如果Session中有Hibernate的持久化对象(通过list()等获得的对象)。在利用Kryo做序列化时会有很多问题。

 

在看了MSM和Kryo的一部分源码后,得到以下解决方案:

在Context-Manager 标签中配置以下属性:

customConverter="xx.xxKryoRegistration"

<Context docBase="xx" path="/xx" crossContext="true" debug="3" privileged="true" reloadable="true">
	<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
		memcachedNodes="n1:xxxxxxxx:11211" requestUriIgnorePattern=".*\.(png|gif|jpg|css|js)$"
		sticky="false"
		lockingMode="auto"
		sessionBackupAsync="false"
		sessionBackupTimeout="60000"
		memcachedProtocol="binary"
		copyCollectionsForSerialization="true"
		transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
		customConverter="xx.xxKryoRegistration" />
</Context>

这个时候因为xx.xxKryoRegistration中需要关联项目中的Hibernate包。所以context配置需要放在当前项目中。或者用其它延迟加载的办法。不然会报找不到类。

 

创建类xx.xxKryoRegistration 并打成jar包;

代码如下:

package xx;

import org.hibernate.proxy.HibernateProxy;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;

import de.javakaffee.web.msm.serializer.kryo.KryoCustomization;
import de.javakaffee.web.msm.serializer.kryo.SerializerFactory;

public class xxKryoRegistration implements KryoCustomization,
		SerializerFactory {
	private Kryo kryo;

	public xxKryoRegistration (Kryo kryo) {
		this.kryo = kryo;
	}

	@Override
	public void customize(Kryo kryo) {
	}

	@Override
	public Serializer newSerializer(Class<?> type) {
		if (HibernateProxy.class.isAssignableFrom(type)) {
			return new HibernateProxySerializer(kryo);
		}
		return null;
	}
}

 HibernateProxySerializer 代码如下:

 

package xx;

import java.nio.ByteBuffer;

import org.hibernate.Hibernate;
import org.hibernate.proxy.HibernateProxy;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.serialize.FieldSerializer;

public class HibernateProxySerializer extends Serializer {
	private Kryo kryo;

	public HibernateProxySerializer(Kryo kryo) {
		this.kryo = kryo;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void writeObjectData(ByteBuffer buffer, Object object) {
		//处理空:
		if (object == null) {
			buffer.put((byte) 0);
		}
		
		Object serialObj = object;
		Class<? extends Object> realType = object.getClass();
		//判断是否是Hibernate的代理类
		if (object instanceof HibernateProxy) {
			//取真实类型
			realType = ((HibernateProxy) object).getHibernateLazyInitializer()
					.getPersistentClass();
			//判断是否已加载,如果未加载,直接创建空对象,或者直接写空值(buffer.put((byte)0))
			if (!Hibernate.isInitialized(object)) {
				try {
					serialObj = ((HibernateProxy) object)
							.getHibernateLazyInitializer().getPersistentClass()
							.newInstance();
				} catch (Exception e) {
					serialObj = null;
				}
			} else {
				//否则直接取加载好的真实类型的对象
				serialObj = ((HibernateProxy) object)
						.getHibernateLazyInitializer().getImplementation();
			}
		}
		new FieldSerializer(kryo, realType).writeObject(buffer, serialObj);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T readObjectData(ByteBuffer buffer, Class<T> type) {
		Class<? extends Object> realType = type;
		//取真实类型
		if (HibernateProxy.class.isAssignableFrom(type)) {
			realType = type.getSuperclass();
		}
		//按照真实类型解析对象
		return (T) new FieldSerializer(kryo, realType).readObject(buffer,
				realType);
	}
}

 然后发现不行额。

继续寻找中。

posted @ 2014-08-29 13:45  时阳  阅读(987)  评论(1编辑  收藏  举报