Spring会话将序列化对象存储在我的数据库中。问题是,有时我的代码会发生变化。有时我的对象会改变。这个是正常的。但是,我得到这样的错误:
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [byte[]] to type [java.lang.Object] for value '{-84, ..., 112}'; 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.mysite.MyClass; local class incompatible: stream classdesc serialVersionUID = 1432849980928799324, local class serialVersionUID = 8454085305026634675
我通过使用HttpSession作为参数调用Spring Boot端点来获取此错误,例如:
@GetMapping("/stuff")
public @ResponseBody MyClass getStuff(HttpSession session) {
try {
Object myObject = session.getAttribute("MyClass");
if (myObject != null && myObject instanceof MyClass) {
return (MyClass) myObject;
} else {
return null;
}
} catch (Exception e) {
logger.warn("Invalid session data", e);
return null;
}
}
但是,因为在调用方法之前抛出异常,我无法从此正常的预期错误中恢复。
作为一种解决方法,我被迫删除每个部署的整个会话表,即使大多数对象仍然兼容!
要清楚,解决方案是不添加serialVersionUuid。因为对象确实以不兼容的方式从一个部署更改为下一个部署。这不是序列化问题。这是一个Spring Session错误恢复问题。
我的问题是:我如何从这些问题中优雅地恢复?
您没有提供详细信息,但我假设您正在使用@EnableJdbcHttpSession
启用的Spring的JDBC会话实现?
在这种情况下,你可以看看JdbcHttpSessionConfiguration
,特别是在setSpringSessionConversionService
和setConversionService
。我相信如果您提供自己的实现(您可以在createConversionServiceWithBeanClassLoader
上看到示例),那么您应该能够捕获反序列化错误并返回空会话。
我认为你需要的是从MyNotFailingSessionDeserializer
派生DeserializingConverter
,覆盖convert
方法,捕捉SerializationFailedException
并返回null或空会话(不确定是否有效)。
然后你创建你的转换服务,如createConversionServiceWithBeanClassLoader
,但使用你的MyNotFailingSessionDeserializer
而不是DeserializingConverter