使用EhCache v3.5.2实现堆内缓存时遇‘无序列化器’错误求助
解决EhCache 3.5.2堆内缓存「No serializer found」错误
这个问题我之前在项目里也踩过坑——别以为堆内缓存就不用序列化,EhCache 3.x的堆内 tier 虽然把对象存在JVM堆中,但内部在处理缓存的一些核心逻辑(比如状态同步、统计或者持久化前的准备)时,依然需要序列化支持。你的MyObj类既没实现标准序列化接口,也没配置自定义序列化器,所以就触发了这个错误。
下面给你两种可行的解决办法:
方法一:让自定义对象实现Serializable接口(快速解决)
这是最直接的方案,让你的MyObj类实现Java标准的Serializable接口,EhCache会自动使用Java序列化来处理对象:
public class TestEhCache { public static class MyObj implements Serializable { // 推荐添加序列化ID,避免类结构变化后出现序列化兼容问题 private static final long serialVersionUID = 1L; String message; public MyObj(String message) { this.message = message; } } @Test public void testDebugLogs() { CacheManager cacheManager; cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(); cacheManager.init(); // 构建缓存配置,现在MyObj可序列化,不会报错 Cache<String, MyObj> myCache = cacheManager.createCache("myCache", CacheConfigurationBuilder.newCacheConfigurationBuilder( String.class, MyObj.class, ResourcePoolsBuilder.heap(100) // 指定堆内缓存大小 ) ); // 测试存取值 myCache.put("key1", new MyObj("Hello EhCache!")); System.out.println(myCache.get("key1").message); cacheManager.close(); } }
方法二:配置自定义序列化器(灵活扩展)
如果不想用Java序列化(比如追求更高性能、不想暴露序列化ID),可以给EhCache配置自定义的序列化器。比如用Jackson的JSON序列化,或者自己实现Serializer接口:
步骤1:实现自定义序列化器
public class MyObjSerializer implements Serializer<MyObj> { @Override public ByteBuffer serialize(MyObj object) throws SerializerException { // 这里用Jackson将对象转为JSON字节数组 try { ObjectMapper mapper = new ObjectMapper(); byte[] bytes = mapper.writeValueAsBytes(object); return ByteBuffer.wrap(bytes); } catch (JsonProcessingException e) { throw new SerializerException("Failed to serialize MyObj", e); } } @Override public MyObj read(ByteBuffer binary) throws ClassNotFoundException, SerializerException { // 反序列化JSON字节数组为MyObj try { ObjectMapper mapper = new ObjectMapper(); byte[] bytes = new byte[binary.remaining()]; binary.get(bytes); return mapper.readValue(bytes, MyObj.class); } catch (IOException e) { throw new SerializerException("Failed to deserialize MyObj", e); } } @Override public boolean equals(Object object) { return object instanceof MyObjSerializer; } }
步骤2:在缓存配置中指定序列化器
@Test public void testDebugLogs() { CacheManager cacheManager; cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(); cacheManager.init(); Cache<String, MyObj> myCache = cacheManager.createCache("myCache", CacheConfigurationBuilder.newCacheConfigurationBuilder( String.class, MyObj.class, ResourcePoolsBuilder.heap(100) ) // 配置自定义序列化器 .withSerializer(MyObj.class, new MyObjSerializer()) ); myCache.put("key1", new MyObj("Hello Custom Serializer!")); System.out.println(myCache.get("key1").message); cacheManager.close(); }
注意事项
- 如果用方法一,记得给序列化类添加
serialVersionUID,避免类结构变化后出现反序列化失败的问题。 - 如果你用的是EhCache的集群功能,序列化会更重要,堆外或磁盘缓存也必须配置序列化。
内容的提问来源于stack exchange,提问作者isvirkina
相关产品推荐
相关产品推荐

