ehcache 3.* 使用介绍

发布时间:2019-09-20 07:36:53编辑:auto阅读(1973)

    官网地址:http://×××w.ehcache.org/documentation/3.6/getting-started.html

        根据官网的说明使用起来非常简单,尤其是在3.0之后, 不管事xml配置文件还是链式编码配置。

    先看示例:

    ResourcePoolsBuilder resourcePoolsBuilder = ResourcePoolsBuilder.newResourcePoolsBuilder().heap(20, MemoryUnit.MB).offheap(30, MemoryUnit.MB);
    CacheConfiguration<String, Object> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, Object.class, resourcePoolsBuilder)
            .withValueSerializer(new PlainJavaSerializer<>(this.getClass().getClassLoader()))
            .withExpiry(ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofHours(24))).build();
    org.ehcache.CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
            .withDefaultSizeOfMaxObjectSize(500, MemoryUnit.KB)
            .withDefaultSizeOfMaxObjectGraph(2000)
            .withCache(CACHE_NAME_CHINESE_DIC, cacheConfiguration)
            .withCache(CACHE_NAME_ENGLISH_DIC, cacheConfiguration)
            .build(true);

    重要的几个知识点:

    ehcache是分层缓存的

    TiersHierarchy.png

    • heap 堆内缓存,也就是存储在JVM内存中;

    • off heap 堆外缓存,非JVM单独非配的一部分内存。因此,设置的参数要与jvm启动参数相协调。

    • disk 磁盘缓存,也就是将缓存内容写入到磁盘文件中。

    • cluster 集群缓存,它是需要已cluster服务器来处同步存储这些数据。

    注意:

       1.heap是必须配置的;

       2.disk tier不能与cluster tier共存,因为,它们回产生不一致;

       3.个缓存tier是金字塔的配置,也就是 heap > off heap > disk > cluster,并且配置的大小是一次递增。

       4.除了heap tier之外,其它层都必须设置key和value的序列化器和反序列化器。另外基础数据类型,已经实现其对相应的序列化/反序列化器。   


    ResourcePoolsBuilder是每个cache独立的,它仅仅只是配置信息。如:如果配置heap=20M,那么每个cache都有20M.


    过期时间设置策略

       如:withExpiry(ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofHours(24))

    1. no expiry 永不过期

    2. time-to-live 从缓存开始计算,所存储的时间

    3. time-to-idle 最后一次使用后计算,所存储的时间


    UserManagedCache

     一个功能不需要太全,但能满足基本的缓存,则使用此类。

    UserManagedCache<Long, String> userManagedCache = UserManagedCacheBuilder.newUserManagedCacheBuilder(Long.class, String.class).build(false);  
    userManagedCache.init();

    注:build(false)时,需要调用init()方法才有效。


    此外,ehcache还有很多其他的设置,比如事务机制,集群,自定义线程池,自定义序列化器和反序列化器等等。在此就不在赘述,官网很详细。


    springboot整合ehcache

    由于版本的不同,之前的springboot集成的时3.0之前的jar, 但是从3.0之后,依赖地址有net.sfn.ehache.*改为org.apache.echache.*。因此,自己注入了sprintboot cacheManager的实现。

    代码如下:

    <dependency>
        <groupId>org.ehcache</groupId>
        <artifactId>ehcache</artifactId>
        <version>3.6.2</version>
    </dependency>


    @Configuration
    @EnableCaching
    public class CacheConfig {
        private static final Logger LOGGER = LoggerFactory.getLogger(CacheConfig.class);
        private static final String CACHE_NAME_XXXX = "XXXX";
        private static final String CACHE_NAME_YYYY = "YYYY";
    
        @Bean
        public CacheManager cacheManager() {
            ResourcePoolsBuilder resourcePoolsBuilder = ResourcePoolsBuilder.newResourcePoolsBuilder().heap(20, MemoryUnit.MB).offheap(30, MemoryUnit.MB);
            CacheConfiguration<String, Object> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, Object.class, resourcePoolsBuilder)
                    .withValueSerializer(new PlainJavaSerializer<>(this.getClass().getClassLoader()))
                    .withExpiry(ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofHours(24))).build();
            org.ehcache.CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                    .withDefaultSizeOfMaxObjectSize(500, MemoryUnit.KB)
                    .withDefaultSizeOfMaxObjectGraph(2000)
                    .withCache(CACHE_NAME_XXXX , cacheConfiguration)
                    .withCache(CACHE_NAME_YYYY, cacheConfiguration)
                    .build(true);
            return new CacheManager() {
                @Override
                public Cache getCache(String name) {
                    org.ehcache.Cache<String, Object> heapEhcache = cacheManager.getCache(name, String.class, Object.class);
                    return new Cache() {
                        @Override
                        public String getName() {
                            return name;
                        }
    
                        @Override
                        public Object getNativeCache() {
                            return heapEhcache;
                        }
    
                        @Override
                        public ValueWrapper get(Object key) {
                            Object value = heapEhcache.get(String.valueOf(key));
                            return null == value ? null : () -> value;
                        }
    
                        @Override
                        public <T> T get(Object key, Class<T> type) {
                            Object value = heapEhcache.get(String.valueOf(key));
                            if (value != null && type != null && !type.isInstance(value)) {
                                throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value);
                            }
                            return (T) value;
                        }
    
                        @Override
                        public <T> T get(Object key, Callable<T> valueLoader) {
                            try {
                                return valueLoader.call();
                            } catch (Exception e) {
                                LOGGER.error("ehcache valueLoader.call occur error", e);
                            }
                            return null;
                        }
    
                        @Override
                        public void put(Object key, Object value) {
                            heapEhcache.put(String.valueOf(key), value);
                        }
    
                        @Override
                        public ValueWrapper putIfAbsent(Object key, Object value) {
                            Object putIfAbsent = heapEhcache.putIfAbsent(String.valueOf(key), value);
                            return putIfAbsent == null ? null : () -> putIfAbsent;
                        }
    
                        @Override
                        public void evict(Object key) {
                            heapEhcache.remove(String.valueOf(key));
                        }
    
                        @Override
                        public void clear() {
                            heapEhcache.clear();
                        }
                    };
                }
    
                @Override
                public Collection<String> getCacheNames() {
                    String[] cacheNames = {CACHE_NAME_XXXX , CACHE_NAME_YYYY};
                    return Arrays.asList(cacheNames);
                }
            };
        }
    }

    注意: 返回类型为ValueWrapper的Cache接口需要注意,源码提示:当返回为null说明缓存中没有此key,则直接返回null,然后就会从数据库中取数据。当有返回值时,说明缓存中有此key, 此时应该返回ValueWrapper的包裹类(包含了实际的返回值)。


关键字