从Helidon 2.5.4升级到3.2.0时遇反序列化异常求助
解决Helidon 3.2.0迁移中Hibernate反序列化URI的
InvalidClassException问题 问题核心
迁移后Hibernate在merge操作时尝试深度拷贝java.net.URI对象,触发Java序列化过滤器拦截,抛出java.io.InvalidClassException: filter status: REJECTED。这是因为Helidon 3.x默认启用了更严格的序列化安全规则,而Hibernate将URI视为Serializable类型,在深度拷贝时触发了序列化流程。
解决思路
1. 将URI加入Helidon序列化允许列表
Helidon 3.x自带序列化过滤机制,需要显式允许java.net.URI类通过过滤。在配置文件(如application.yaml)中添加:
helidon: serialization: filter: include-classes: java.net.URI
如果需要同时允许其他类,用逗号分隔:java.net.URI,java.util.UUID
也可以通过JVM启动参数临时配置:
-Djdk.serialFilter=java.net.URI;*
2. 自定义Hibernate JavaType避免序列化拷贝
Hibernate默认对Serializable类型使用序列化方式做深度拷贝,我们可以自定义JavaType,直接通过字符串拷贝URI,绕过序列化:
步骤1:实现自定义JavaType
import org.hibernate.type.descriptor.java.MutableMutabilityPlan; import org.hibernate.type.descriptor.java.JavaType; import java.net.URI; public class UriJavaType implements JavaType<URI> { @Override public Class<URI> getJavaType() { return URI.class; } @Override public MutabilityPlan<URI> getMutabilityPlan() { return new MutableMutabilityPlan<>() { @Override public URI deepCopy(URI value) { // 直接通过字符串重建URI,避免序列化 return value != null ? URI.create(value.toString()) : null; } @Override public boolean isMutable() { return false; // URI本身是不可变类型 } }; } @Override public String toString(URI value) { return value != null ? value.toString() : null; } @Override public URI fromString(CharSequence string) { return string != null ? URI.create(string.toString()) : null; } }
步骤2:在实体属性上使用该JavaType
@Column(name = "FILE_URI") @Convert(converter = UriAttributeConverter.class) @JavaType(UriJavaType.class) // 添加这一行 @Nullable private URI fileUri; @Nullable @Column(name = "APPLICATION_URI") @Convert(converter = UriAttributeConverter.class) @JavaType(UriJavaType.class) // 添加这一行 private URI applicationUri;
3. 确保AttributeConverter正确实现
检查你的UriAttributeConverter是否正确处理URI与字符串的转换,建议开启全局自动应用:
import jakarta.persistence.AttributeConverter; import jakarta.persistence.Converter; import java.net.URI; @Converter(autoApply = true) // 全局自动应用,无需每个属性加@Convert public class UriAttributeConverter implements AttributeConverter<URI, String> { @Override public String convertToDatabaseColumn(URI attribute) { return attribute != null ? attribute.toString() : null; } @Override public URI convertToEntityAttribute(String dbData) { return dbData != null ? URI.create(dbData) : null; } }
4. 优化Hibernate操作避免不必要的merge
如果测试中是merge操作触发的问题,可以尝试:
- 确保实体处于托管状态后再修改属性,无需调用merge
- 用
persist或update替代merge,减少深度拷贝场景
内容的提问来源于stack exchange,提问作者user3226611
相关产品推荐
相关产品推荐

