有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java EhCache磁盘持久性可以持久化任意对象

我想使用EhCache在磁盘上持久化对象,所以下次我将运行我的应用程序时,它将从中加载。在他们的文档中,有以下使用PersistentCacheManager类执行此操作的示例:

PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder().with(CacheManagerBuilder.persistence(new File(getStoragePath(), "myData"))).withCache("persistent-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
ResourcePoolsBuilder.newResourcePoolsBuilder().disk(10, MemoryUnit.MB, true))).build(true);
persistentCacheManager.close();

该示例运行良好,但如果CacheConfigurationBuilder对象定义了硬编码为Long和String的键和值的类,那么我就有问题了。我希望保留仲裁类的实例,而不是预定义哪些实例。此外,CacheConfigurationBuilder不会接受对象。类或哈希映射。例如,类

如何使用EhCache在磁盘上持久化任意实例类


共 (1) 个答案

  1. # 1 楼答案

    Ehcache可以接受任何键或值。默认情况下,它要求它们必须是可序列化的。否则,它无法知道如何将其存储在堆外或磁盘上

    HashMap是可序列化的,因此您不会从中得到警告Map不是。因此,您会得到一个警告,但如果实现实际上是可序列化的,那么它仍然可以工作

    然而,如果您确实存储了一个不可序列化的对象,那么您确实会得到一个异常。解决方案是指定一个键和/或值序列化程序,告诉Ehcache如何存储所需的内容。完整的文档是there

    现在让我们看一个例子。您需要一个要缓存的类MyClass

    public class MyClass {
      private String value;
    
      public MyClass(String value) {
        this.value = value;
      }
    
      public String getValue() {
        return value;
      }
    
      @Override
      public boolean equals(Object o) {
        if(this == o) { return true; }
        if(o == null || getClass() != o.getClass()) { return false; }
        MyClass myClass = (MyClass) o;
        return Objects.equals(value, myClass.value);
      }
    
      @Override
      public int hashCode() {
        return value != null ? value.hashCode() : 0;
      }
    }
    

    还有一个测试,确保它能正常工作

    @Test
    public void test() {
      try(CacheManager persistentCacheManager =
            newCacheManagerBuilder()
              .withCache("test-cache",
                newCacheConfigurationBuilder(Integer.class, MyClass.class,
                  newResourcePoolsBuilder().offheap(1, MemoryUnit.MB)))
              .withSerializer(MyClass.class, MySerializer.class)
              .build(true)) {
    
        Cache<Integer, MyClass> cache = persistentCacheManager.getCache("test-cache", Integer.class, MyClass.class);
        cache.put(1, new MyClass("test"));
        MyClass actual = cache.get(1);
        assertEquals("test", actual.getValue());
      }
    
    }
    

    您的序列化程序将如下所示:

    public class MySerializer implements Serializer<MyClass> {
    
      public MySerializer(ClassLoader unused) {
      }
    
      @Override
      public ByteBuffer serialize(MyClass object) throws SerializerException {
        try(ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oout = new ObjectOutputStream(bout)) {
          oout.writeUTF(object.getValue());
          oout.flush();
          return ByteBuffer.wrap(bout.toByteArray());
        } catch (IOException e) {
          throw new SerializerException(e);
        }
      }
    
      @Override
      public MyClass read(ByteBuffer binary) throws ClassNotFoundException, SerializerException {
        try(ObjectInputStream oin = new ObjectInputStream(new ByteBufferInputStream(binary))) {
            return new MyClass(oin.readUTF());
        } catch (IOException e) {
          throw new SerializerException(e);
        }
      }
    
      @Override
      public boolean equals(MyClass object, ByteBuffer binary) throws ClassNotFoundException, SerializerException {
        return object.equals(read(binary));
      }
    
    }