2017-08-13 5 views
3

Je veux utiliser EhCache pour conserver les objets sur le disque, donc la prochaine fois que j'utiliserai mon application, elle sera chargée. Dans la documentation, il est l'exemple suivant pour l'utilisation de la classe PersistentCacheManager de le faire:Persistance disque EhCache - persister un objet arbitraire

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

L'exemple fonctionne très bien, mais le problème pour moi si que l'objet CacheConfigurationBuilder définit les classes de la clé et la valeur codée en dur à Long et String Je voudrais persister des instances de classes arbitraires et ne pas prédéfinir lesquelles. En outre, CacheConfigurationBuilder ne prend pas Object.class ou HashMap.class, par exemple. Comment puis-je utiliser EhCache pour conserver sur disque une classe d'instance arbitraire?

Comment utiliser EhCache pour conserver sur disque une classe d'instance arbitraire?

+0

Selon les (http://www.ehcache.org/apidocs/3.0.3/org/ehcache/config/builders [docs] /CacheConfigurationBuilder.html#newCacheConfigurationBuilder-java.lang.Class-java.lang.Class-org.ehcache.config.Builder-) la clé et la valeur peuvent être de n'importe quel type - l'exemple utilise Long et String mais cela ne veut pas dire vous êtes limité à utiliser uniquement ces types! – alfasin

+0

Les types Object ou HashMap entraînent une exception d'exécution indiquant que le type n'est pas serialazble. –

+0

Ensuite, utilisez des types sérialisables;) – alfasin

Répondre

2

Ehcache peut prendre n'importe quelle clé ou valeur. Par défaut, il faut qu'ils soient sérialisables. Dans le cas contraire, il ne peut pas savoir comment le stocker hors-stock ou sur disque.

HashMap est sérialisable, vous n'obtiendrez donc pas d'avertissement. Map ne l'est pas. Donc, vous obtiendrez un avertissement, mais cela fonctionnera toujours si l'implémentation est en fait sérialisable.

Cependant, si vous stockez vraiment un objet non sérialisable, vous obtenez une exception. La solution est de spécifier une clé et/ou un sérialiseur de valeur indiquant à Ehcache comment stocker ce que vous voulez. La documentation complète est there.

Maintenant, regardons un exemple. Vous avez une classe MyClass que vous voulez mettre en cache.

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

Et un test pour s'assurer que cela fonctionne.

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

} 

Votre sérialiseur ressemblera à ceci:

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

Pourriez-vous élaborer sur la dernière partie de votre réponse, en ce qui concerne le stockage de l'objet qui n'est pas sérialisable, et peut-être donner un exemple de code? –

+0

Voici un exemple – Henri