异常名称
Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.InvalidClassException: com.msun.dms.security.pojo.SecurityLoginUser; local class incompatible: stream classdesc serialVersionUID = 520, local class serialVersionUID = 530
从异常信息中可以看出是SecurityLoginUser类出现问题,(SecurityLoginUser是自定义的类,如下代码示例),
@Data
public class SecurityLoginUser<T extends Users> implements UserDetails, CredentialsContainer {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private LoginUser<T> loginUser;
public SecurityLoginUser(LoginUser<T> user) {
this.loginUser = user;
}
public String username;
................还有其余代码,和本次异常无关
}
里面最重要的是规定了一个序列化id:
serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
而此序列化id使用了SpringSecurityCore包中的SERIAL_VERSION_UID字段,这个字段根据security版本的不同会有所变化,所以如果两个微服务项目中引用了不同的security版本就会导致反序列化失败。如下两个服务的security版本。
序列化知识补充:
serialVersionUID 是 Java 为每个序列化类产生的版本标识,可用来保证在反序列时,发送方发送的和接受方接收的是可兼容的对象。如果接收方接收的类的 serialVersionUID 与发送方发送的 serialVersionUID 不一致,进行反序列时会抛出 InvalidClassException。序列化的类可显式声明 serialVersionUID 的值。
当显式定义 serialVersionUID 的值时,Java 根据类的多个方面(具体可参考 Java 序列化规范)动态生成一个默认的 serialVersionUID 。尽管这样,还是建议你在每一个序列化的类中显式指定 serialVersionUID 的值,因为不同的 jdk 编译很可能会生成不同的 serialVersionUID 默认值,进而导致在反序列化时抛出 InvalidClassExceptions 异常。所以,为了保证在不同的 jdk 编译实现中,其 serialVersionUID 的值也一致,可序列化的类必须显式指定 serialVersionUID 的值。另外,serialVersionUID 的修饰符最好是 private,因为 serialVersionUID 不能被继承,所以建议使用 private 修饰 serialVersionUID。