在用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);
}
}
然后发现不行额。
继续寻找中。