2017-08-13 1 views
3

Ich möchte mit EhCache Objekte auf der Festplatte persistent, so dass ich in der nächsten Zeit, die ich meine App ausführen wird es von ihm geladen wird. In ihrer Dokumentation gibt es das folgende Beispiel für PersistentCacheManager-Klasse, dies zu tun:EhCache Festplatte Persistenz - persist ein beliebiges Objekt

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

Das Beispiel funktioniert gut, aber das Problem für mich, wenn das der CacheConfigurationBuilder Objekt definiert die Klassen der Schlüssel und Wert hart codiert Lange und Schnur. Ich möchte Instanzen von Schiedsgerichtsklassen beibehalten und nicht festlegen, welche. Außerdem würde der CacheConfigurationBuilder beispielsweise nicht Object.class oder HashMap.class verwenden.

Wie kann ich EhCache verwenden, um eine beliebige Instanzklasse auf dem Datenträger zu erhalten?

+0

Nach dem [docs] (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-) Der Schlüssel und Wert kann von jedem Typ sein - das Beispiel verwendet Long und String, aber das bedeutet nicht Sie können nur diese Typen verwenden! – alfasin

+0

Typen Object oder HashMap führen zu einer Laufzeitausnahme, die besagt, dass der Typ nicht serialisiert ist. –

+0

Dann verwenden Sie serialisierbare Typen;) – alfasin

Antwort

2

Ehcache kann einen beliebigen Schlüssel oder Wert annehmen. Standardmäßig müssen sie serialisierbar sein. Andernfalls kann es nicht wissen, wie es außerhalb des Laufwerks oder auf der Festplatte gespeichert wird.

HashMap ist serialisierbar, daher erhalten Sie keine Warnung. Map ist nicht. Sie würden also eine Warnung erhalten, aber es funktioniert immer noch, wenn die Implementierung serialisierbar ist.

Wenn Sie jedoch wirklich ein Objekt speichern, das nicht serialisierbar ist, erhalten Sie in der Tat eine Ausnahme. Die Lösung besteht darin, einen Schlüssel und/oder einen Wert-Serialisierer anzugeben, der Ehcache mitteilt, wie alles zu speichern ist. Die vollständige Dokumentation ist there.

Schauen wir uns nun ein Beispiel an. Sie eine Klasse MyClass, die Sie zwischenspeichern möchten.

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

Und ein Test, der sicherstellt, dass es funktioniert.

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

} 

Ihre Serializer werden wie folgt aussehen:

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

Könnten Sie den letzten Teil Ihrer Antwort näher erläutern, in Bezug auf die Speicherung von Objekten, die nicht serialisierbar sind, und vielleicht ein Codebeispiel geben? –

+0

Hier ist ein Beispiel – Henri

Verwandte Themen