2017-08-13 102 views
3

我想使用EhCache來堅持磁盤上的對象,所以下次我將運行我的應用程序,它會從它加載。在他們的文檔,存在一種使用PersistentCacheManager類這樣做下面的例子:EhCache磁盤持久化 - 堅持一個任意對象

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對象定義鍵和值硬編碼到的類長和字符串。我想堅持仲裁課的實例,而不是預先定義哪些實例。另外,例如,CacheConfigurationBuilder不會採用Object.class或HashMap.class。

如何使用EhCache在磁盤上堅持一個任意實例類?

+0

按照[文檔](http://www.ehcache.org/apidocs/3.0.3/org/ehcache/config/builders /CacheConfigurationBuilder.html#newCacheConfigurationBuilder-java.lang.Class-java.lang.Class-org.ehcache.config.Builder-)鍵和值可以是任何類型 - 示例使用Long和String,但這並不意味着你只能使用這些類型! – alfasin

+0

類型Object或HashMap導致運行時異常,表明該類型不可調整。 –

+0

然後使用可序列化的類型;) – alfasin

回答

2

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)); 
    } 

} 
+0

您能否詳細說明答案的最後部分,關於不可序列化的對象的存儲,並且可能給出一個代碼示例? –

+0

這裏是一個例子 – Henri