美文网首页
Spring Cache

Spring Cache

作者: Minato666 | 来源:发表于2019-01-17 22:54 被阅读0次

    在我们日常编码中,cache是很常见的,在没有使用spring cache之前,我们可能会使用下面这种代码来实现cache:

    public class MyCacheManager<T> { 
      private Map<String,T> cache = 
          new ConcurrentHashMap<String,T>(); 
      
      public T getValue(Object key) { 
        return cache.get(key); 
      } 
      
      public void addOrUpdateCache(String key,T value) { 
        cache.put(key, value); 
      } 
      
      public void evictCache(String key) {// 根据 key 来删除缓存中的一条记录
        if(cache.containsKey(key)) { 
          cache.remove(key); 
        } 
      } 
      
      public void evictCache() {// 清空缓存中的所有记录
        cache.clear(); 
      } 
    }
    

    然后在使用的地方使用该cacheManage 缓存和获取数据。缺点就是和业务代码耦合度比较高,不灵活,不能灵活切换第三方缓存模块。而如果使用Spring Cahce就可以杜绝这些问题。
    Spring Cache使用非常简单,这里我们使用ehcache作为spring cache的cache manager。由于spring 自带的cachemanager不支持缓存定期失效刷新,所以我们采用ehcache。

    • 第一步引入jar包
      这里列出关键的两个包:
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>net.sf.ehcache</groupId>
                <artifactId>ehcache</artifactId>
                <version>2.8.2</version>
            </dependency>
    
    • 第二步
      applicationContext.xml 中加入下面的配置:
    <cache:annotation-driven/>
    <bean id="ehcache"  class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
              p:config-location="classpath:ehcache.xml"
              p:shared="true"/>
    
        <bean id="cacheManager"
              class="org.springframework.cache.ehcache.EhCacheCacheManager"
              p:cache-manager-ref="ehcache"/>
    

    classpath下加入ehcache.xml 配置

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache updateCheck="false">
       <!-- 指定一个文件目录,当EhCache把数据写到硬盘上时,将把数据写到这个文件目录下 -->
       <diskStore path="java.io.tmpdir"/>
    
       <cache name="SystemConfigCache"
              maxElementsInMemory="1000"
              eternal="false"
              overflowToDisk="false"
              timeToIdleSeconds="600"
              timeToLiveSeconds="700"/>
    
    </ehcache>
    

    注意其中的cache name,这个是我们后面配置要用到的,

    eternal:true表示对象永不过期,此时会忽略timeToIdleSeconds和timeToLiveSeconds属性,默认为false。
    timeToIdleSeconds: 设定允许对象处于空闲状态的最长时间,以秒为单位。当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性 值,这个对象就会过期,EHCache将把它从缓存中清空。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限 期地处于空闲状态
    timeToLiveSeconds:设定对象允许存在于缓存中的最长时间,以秒为单位。当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清除。只有当eternal属性为false,该属性才有 效。如果该属性值为0,则表示对象可以无限期地存在于缓存中。timeToLiveSeconds必须大于timeToIdleSeconds属性,才有意义
    
    • 第三步 编写cache类
    package com.oocl.ir4.sps.service.cache;
    
    import com.oocl.ir4.sps.dao.common.SystemConfigDao;
    import com.oocl.ir4.sps.entity.common.SystemConfig;
    import org.springframework.cache.annotation.CacheConfig;
    import org.springframework.cache.annotation.CacheEvict;
    import org.springframework.cache.annotation.Cacheable;
    
    import javax.annotation.Resource;
    
    @CacheConfig(cacheNames = "SystemConfigCache")
    public class SystemConfigCache {
    
        @Resource
        SystemConfigDao systemConfigDao;
    
    
        @Cacheable( key = "'SystemConfig_' + #key")
        public SystemConfig getConfigByKey(String key) {
            System.out.print("read from db ===================================");
            return systemConfigDao.findSystemConfigByKey(key);
        }
    
        @CacheEvict(allEntries = true)
        public void reload() {
    
        }
    
    }
    

    在类上配置了cacheNames,就是之前我们在ehcache.xml配置的。
    其中的getConfigByKey 这个方法,我们给它加了一个annotation,@Cacheable 这个就表示我要把该方法的返回值缓存下来,key就是我们指定的格式”SystemConfig_ + 传入的参数key”.

    如果我们想清空缓存,可以使用@CacheEvict(allEntries = true) ,也就是代码中reload方法。

    运行下面测试:

    @Test
        public void systemConfig() {
            System.out.println("first query");
            SystemConfig systemConfig = systemConfigCache.getConfigByKey(EmailConfig.KEY);
            System.out.println(JsonUtil.writeValueAsPrettyString(systemConfig));
            System.out.println("second query");
            SystemConfig systemConfig1 = systemConfigCache.getConfigByKey(EmailConfig.KEY);
            System.out.println(JsonUtil.writeValueAsPrettyString(systemConfig1));
        }
    

    获得结果:

    first query
    read from db ===================================
    {
      "id" : {
        "time" : 1547704819000,
        "timestamp" : 1547704819,
        "date" : 1547704819000,
        "new" : false,
        "inc" : 493821772,
        "machine" : 1078273087,
        "timeSecond" : 1547704819
      },
      "key" : "EMAIL_CONFIG",
      "value" : "{\"aliyunEmailDomains\":[\"stp.com\"]}"
    }
    second query
    {
      "id" : {
        "time" : 1547704819000,
        "timestamp" : 1547704819,
        "date" : 1547704819000,
        "new" : false,
        "inc" : 493821772,
        "machine" : 1078273087,
        "timeSecond" : 1547704819
      },
      "key" : "EMAIL_CONFIG",
      "value" : "{\"aliyunEmailDomains\":[\"stp.com\"]}"
    }
    

    可以看到第一次是从DB中获取数据,第二次是从cache中获取数据。

    相关文章

      网友评论

          本文标题:Spring Cache

          本文链接:https://www.haomeiwen.com/subject/xxhwdqtx.html