赞
踩
package com.visy.configure;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds=100)
public class ConfigRedisSession {
}
org.springframework.data.redis.serializer.SerializationException: Cannot deserialize;
nested exception is org.springframework.core.serializer.support.SerializationFailedException:
Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?;
nested exception is java.io.InvalidClassException:
com.vz.common.model.User;
local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = -6369326306393228118
package org.springframework.session.data.redis.config.annotation.web.http;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({RedisHttpSessionConfiguration.class})
@Configuration
public @interface EnableRedisHttpSession {
int maxInactiveIntervalInSeconds() default 1800;
String redisNamespace() default "";
RedisFlushMode redisFlushMode() default RedisFlushMode.ON_SAVE;
}
package org.springframework.session.data.redis.config.annotation.web.http; @Configuration @EnableScheduling public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguration implements EmbeddedValueResolverAware, ImportAware { private Integer maxInactiveIntervalInSeconds = 1800; private ConfigureRedisAction configureRedisAction = new ConfigureNotifyKeyspaceEventsAction(); private String redisNamespace = ""; private RedisFlushMode redisFlushMode; private RedisSerializer<Object> defaultRedisSerializer; private Executor redisTaskExecutor; private Executor redisSubscriptionExecutor; private StringValueResolver embeddedValueResolver; public RedisHttpSessionConfiguration() { this.redisFlushMode = RedisFlushMode.ON_SAVE; } @Bean public RedisTemplate<Object, Object> sessionRedisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate(); template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); if (this.defaultRedisSerializer != null) { //如果存在默认序列化器则使用 template.setDefaultSerializer(this.defaultRedisSerializer); } template.setConnectionFactory(connectionFactory); return template; } //设置默认序列化器,寻找名称为”springSessionDefaultRedisSerializer“的RedisSerializer注入 @Autowired( required = false) @Qualifier("springSessionDefaultRedisSerializer") public void setDefaultRedisSerializer(RedisSerializer<Object> defaultRedisSerializer) { this.defaultRedisSerializer = defaultRedisSerializer; } }
package org.springframework.data.redis.core; public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware { public void afterPropertiesSet() { super.afterPropertiesSet(); boolean defaultUsed = false; if (this.defaultSerializer == null) { //默认序列化器是JdkSerializationRedisSerializer this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader()); } if (this.enableDefaultSerializer) { if (this.keySerializer == null) { this.keySerializer = this.defaultSerializer; defaultUsed = true; } if (this.valueSerializer == null) { this.valueSerializer = this.defaultSerializer; defaultUsed = true; } if (this.hashKeySerializer == null) { this.hashKeySerializer = this.defaultSerializer; defaultUsed = true; } if (this.hashValueSerializer == null) { this.hashValueSerializer = this.defaultSerializer; defaultUsed = true; } } if (this.enableDefaultSerializer && defaultUsed) { Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized"); } if (this.scriptExecutor == null) { this.scriptExecutor = new DefaultScriptExecutor(this); } this.initialized = true; } }
默认使用JdkSerializationRedisSerializer反序列化的过程
package org.springframework.data.redis.serializer; public class JdkSerializationRedisSerializer implements RedisSerializer<Object> { public Object deserialize(byte[] bytes) { if (SerializationUtils.isEmpty(bytes)) { return null; } else { try { //反序列化 return this.deserializer.convert(bytes); } catch (Exception var3) { throw new SerializationException("Cannot deserialize", var3); } } } }
package org.springframework.core.serializer.support;
public class DeserializingConverter implements Converter<byte[], Object> {
public Object convert(byte[] source) {
ByteArrayInputStream byteStream = new ByteArrayInputStream(source);
try {
//反序列化
return this.deserializer.deserialize(byteStream);
} catch (Throwable var4) {
throw new SerializationFailedException("Failed to deserialize payload. Is the byte array a result of corresponding serialization for " + this.deserializer.getClass().getSimpleName() + "?", var4);
}
}
}
package org.springframework.core.serializer;
public class DefaultDeserializer implements Deserializer<Object> {
public Object deserialize(InputStream inputStream) throws IOException {
ObjectInputStream objectInputStream = new ConfigurableObjectInputStream(inputStream, this.classLoader);
try {
//读取对象
return objectInputStream.readObject();
} catch (ClassNotFoundException var4) {
throw new NestedIOException("Failed to deserialize object type", var4);
}
}
}
package java.io; public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants { public final Object readObject() throws IOException, ClassNotFoundException { return readObject(Object.class); } private final Object readObject(Class<?> type) throws IOException, ClassNotFoundException { if (enableOverride) { return readObjectOverride(); } if (! (type == Object.class || type == String.class)) throw new AssertionError("internal error"); // if nested read, passHandle contains handle of enclosing object int outerHandle = passHandle; try { Object obj = readObject0(type, false); handles.markDependency(outerHandle, passHandle); ClassNotFoundException ex = handles.lookupException(passHandle); if (ex != null) { throw ex; } if (depth == 0) { vlist.doCallbacks(); } return obj; } finally { passHandle = outerHandle; if (closed && depth == 0) { clear(); } } } private Object readObject0(Class<?> type, boolean unshared) throws IOException { boolean oldMode = bin.getBlockDataMode(); if (oldMode) { int remain = bin.currentBlockRemaining(); if (remain > 0) { throw new OptionalDataException(remain); } else if (defaultDataEnd) { /* * Fix for 4360508: stream is currently at the end of a field * value block written via default serialization; since there * is no terminating TC_ENDBLOCKDATA tag, simulate * end-of-custom-data behavior explicitly. */ throw new OptionalDataException(true); } bin.setBlockDataMode(false); } byte tc; while ((tc = bin.peekByte()) == TC_RESET) { bin.readByte(); handleReset(); } depth++; totalObjectRefs++; try { switch (tc) { case TC_NULL: return readNull(); case TC_REFERENCE: // check the type of the existing object return type.cast(readHandle(unshared)); case TC_CLASS: if (type == String.class) { throw new ClassCastException("Cannot cast a class to java.lang.String"); } return readClass(unshared); case TC_CLASSDESC: case TC_PROXYCLASSDESC: if (type == String.class) { throw new ClassCastException("Cannot cast a class to java.lang.String"); } return readClassDesc(unshared); case TC_STRING: case TC_LONGSTRING: return checkResolve(readString(unshared)); case TC_ARRAY: if (type == String.class) { throw new ClassCastException("Cannot cast an array to java.lang.String"); } return checkResolve(readArray(unshared)); case TC_ENUM: if (type == String.class) { throw new ClassCastException("Cannot cast an enum to java.lang.String"); } return checkResolve(readEnum(unshared)); case TC_OBJECT: if (type == String.class) { throw new ClassCastException("Cannot cast an object to java.lang.String"); } return checkResolve(readOrdinaryObject(unshared)); case TC_EXCEPTION: if (type == String.class) { throw new ClassCastException("Cannot cast an exception to java.lang.String"); } IOException ex = readFatalException(); throw new WriteAbortedException("writing aborted", ex); case TC_BLOCKDATA: case TC_BLOCKDATALONG: if (oldMode) { bin.setBlockDataMode(true); bin.peek(); // force header read throw new OptionalDataException( bin.currentBlockRemaining()); } else { throw new StreamCorruptedException( "unexpected block data"); } case TC_ENDBLOCKDATA: if (oldMode) { throw new OptionalDataException(true); } else { throw new StreamCorruptedException( "unexpected end of block data"); } default: throw new StreamCorruptedException( String.format("invalid type code: %02X", tc)); } } finally { depth--; bin.setBlockDataMode(oldMode); } } private ObjectStreamClass readClassDesc(boolean unshared) throws IOException { byte tc = bin.peekByte(); ObjectStreamClass descriptor; switch (tc) { case TC_NULL: descriptor = (ObjectStreamClass) readNull(); break; case TC_REFERENCE: descriptor = (ObjectStreamClass) readHandle(unshared); // Should only reference initialized class descriptors descriptor.checkInitialized(); break; case TC_PROXYCLASSDESC: descriptor = readProxyDesc(unshared); break; case TC_CLASSDESC: descriptor = readNonProxyDesc(unshared); break; default: throw new StreamCorruptedException( String.format("invalid type code: %02X", tc)); } if (descriptor != null) { validateDescriptor(descriptor); } return descriptor; } private ObjectStreamClass readNonProxyDesc(boolean unshared) throws IOException { if (bin.readByte() != TC_CLASSDESC) { throw new InternalError(); } ObjectStreamClass desc = new ObjectStreamClass(); int descHandle = handles.assign(unshared ? unsharedMarker : desc); passHandle = NULL_HANDLE; ObjectStreamClass readDesc = null; try { readDesc = readClassDescriptor(); } catch (ClassNotFoundException ex) { throw (IOException) new InvalidClassException( "failed to read class descriptor").initCause(ex); } Class<?> cl = null; ClassNotFoundException resolveEx = null; bin.setBlockDataMode(true); final boolean checksRequired = isCustomSubclass(); try { if ((cl = resolveClass(readDesc)) == null) { resolveEx = new ClassNotFoundException("null class"); } else if (checksRequired) { ReflectUtil.checkPackageAccess(cl); } } catch (ClassNotFoundException ex) { resolveEx = ex; } // Call filterCheck on the class before reading anything else filterCheck(cl, -1); skipCustomData(); try { totalObjectRefs++; depth++; desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false)); } finally { depth--; } handles.finish(descHandle); passHandle = descHandle; return desc; } }
package java.io; public class ObjectStreamClass implements Serializable { void initNonProxy(ObjectStreamClass model, Class<?> cl, ClassNotFoundException resolveEx, ObjectStreamClass superDesc) throws InvalidClassException { long suid = Long.valueOf(model.getSerialVersionUID()); ObjectStreamClass osc = null; if (cl != null) { osc = lookup(cl, true); if (osc.isProxy) { throw new InvalidClassException( "cannot bind non-proxy descriptor to a proxy class"); } if (model.isEnum != osc.isEnum) { throw new InvalidClassException(model.isEnum ? "cannot bind enum descriptor to a non-enum class" : "cannot bind non-enum descriptor to an enum class"); } if (model.serializable == osc.serializable && !cl.isArray() && suid != osc.getSerialVersionUID()) { throw new InvalidClassException(osc.name, "local class incompatible: " + "stream classdesc serialVersionUID = " + suid + ", local class serialVersionUID = " + osc.getSerialVersionUID()); } if (!classNamesEqual(model.name, osc.name)) { throw new InvalidClassException(osc.name, "local class name incompatible with stream class " + "name \"" + model.name + "\""); } if (!model.isEnum) { if ((model.serializable == osc.serializable) && (model.externalizable != osc.externalizable)) { throw new InvalidClassException(osc.name, "Serializable incompatible with Externalizable"); } if ((model.serializable != osc.serializable) || (model.externalizable != osc.externalizable) || !(model.serializable || model.externalizable)) { deserializeEx = new ExceptionInfo( osc.name, "class invalid for deserialization"); } } } this.cl = cl; this.resolveEx = resolveEx; this.superDesc = superDesc; name = model.name; this.suid = suid; isProxy = false; isEnum = model.isEnum; serializable = model.serializable; externalizable = model.externalizable; hasBlockExternalData = model.hasBlockExternalData; hasWriteObjectData = model.hasWriteObjectData; fields = model.fields; primDataSize = model.primDataSize; numObjFields = model.numObjFields; if (osc != null) { localDesc = osc; writeObjectMethod = localDesc.writeObjectMethod; readObjectMethod = localDesc.readObjectMethod; readObjectNoDataMethod = localDesc.readObjectNoDataMethod; writeReplaceMethod = localDesc.writeReplaceMethod; readResolveMethod = localDesc.readResolveMethod; if (deserializeEx == null) { deserializeEx = localDesc.deserializeEx; } domains = localDesc.domains; cons = localDesc.cons; } fieldRefl = getReflector(fields, localDesc); // reassign to matched fields so as to reflect local unshared settings fields = fieldRefl.getFields(); initialized = true; } }
if (model.serializable == osc.serializable &&
!cl.isArray() &&
suid != osc.getSerialVersionUID()) {
throw new InvalidClassException(osc.name,
"local class incompatible: " +
"stream classdesc serialVersionUID = " + suid +
", local class serialVersionUID = " +
osc.getSerialVersionUID());
}
自定义一个序列化器,不要使用JdkSerializationRedisSerializer
以下是官方给出的自定义默认序列化器的配置方法,点击可查看
@Configuration public class SessionConfig implements BeanClassLoaderAware { private ClassLoader loader; @Bean public RedisSerializer<Object> springSessionDefaultRedisSerializer() { //改用Jackson的序列化器 return new GenericJackson2JsonRedisSerializer(objectMapper()); } /** * Customized {@link ObjectMapper} to add mix-in for class that doesn't have default * constructors * @return the {@link ObjectMapper} to use */ private ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.registerModules(SecurityJackson2Modules.getModules(this.loader)); return mapper; } /* * @see * org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java.lang * .ClassLoader) */ @Override public void setBeanClassLoader(ClassLoader classLoader) { this.loader = classLoader; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。