春季会话,部署后从"local class incompatible"中恢复



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 的 JDBC 会话实现,该实现由@EnableJdbcHttpSession启用?

在这种情况下,您可以查看JdbcHttpSessionConfiguration,尤其是setSpringSessionConversionServicesetConversionService.我相信如果您提供自己的实现(您可以在createConversionServiceWithBeanClassLoader中看到示例(,那么您应该能够捕获反序列化错误并返回空会话。

我认为您所需要的只是从DeserializingConverter中获取MyNotFailingSessionDeserializer,覆盖convert方法,捕获SerializationFailedException并返回 null 或空会话(不确定它们是否有效(。

然后,您可以像createConversionServiceWithBeanClassLoader一样创建转换服务,但使用MyNotFailingSessionDeserializer而不是DeserializingConverter

相关内容

最新更新