推荐ehcache  和    Caffeine   https://blog.csdn.net/sco5282/article/details/142024324 

 

版本:

springboot2.3.12 + ehcache3.x  +  

app + @EnableCaching
application.properties + spring.cache.type=JCACHE

 

依赖:

        <!-- 缓存 -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
          </dependency>
          <!-- ehcache -->
          <dependency>
              <groupId>org.ehcache</groupId>
              <artifactId>ehcache</artifactId>
              <version>3.10.8</version>
          </dependency>
         <dependency>
              <groupId>javax.cache</groupId>
              <artifactId>cache-api</artifactId>
          </dependency>

 

 

 



import com.alibaba.fastjson.JSON;
import org.ehcache.Cache;
import org.ehcache.PersistentCacheManager;
import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ExpiryPolicyBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.core.config.DefaultConfiguration;
import org.ehcache.jsr107.EhcacheCachingProvider;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.jcache.JCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PreDestroy;
import javax.cache.Caching;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

/***************************
 *<pre>
 * @Project Name : bk
 * @Package      : common.config
 * @File Name    : MyEhcacheConfig
 * @Author       :  Sea
 * @Mail         :  lshan523@163.com
 * @Date         : 2024/10/24 14:29
 * @Purpose      :
 * @History      :
 *
 * springboot2.3.12 + ehcache3  +  @EnableCaching   +  config + spring.cache.type=JCACHE
 *         <!-- 缓存 -->
 *         <dependency>
 *             <groupId>org.springframework.boot</groupId>
 *             <artifactId>spring-boot-starter-cache</artifactId>
 *         </dependency>
 *         <!-- ehcache -->
 *         <dependency>
 *             <groupId>org.ehcache</groupId>
 *             <artifactId>ehcache</artifactId>
 *             <version>3.10.8</version>
 *         </dependency>
 *         <dependency>
 *             <groupId>javax.cache</groupId>
 *             <artifactId>cache-api</artifactId>
 *         </dependency>
 *</pre>
 ***************************/
@Configuration
@EnableCaching
public class MyEhcacheConfig {

    private final PersistentCacheManager persistentCacheManager;

    public MyEhcacheConfig() {
        persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                .withCache("dickTokenCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, String.class,
                                ResourcePoolsBuilder.newResourcePoolsBuilder()
                                        .disk(1, MemoryUnit.GB, true))
                        .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofHours(24)))
                        .withEvictionAdvisor((key, value) -> false))
                .with(CacheManagerBuilder.persistence("/opt/cache/token/")) // 缓存目录
                .build(true);
    }

    /**
     * 避免出现 ehcache  Caused by: java.lang.RuntimeException: Persistence directory already locked
     */
    @PreDestroy
    public void shutdown() {
        if (persistentCacheManager != null) {
            persistentCacheManager.close();
        }
    }


    /**
     * 存磁盘缓存,持久化 CacheManager->dickCache
     * @return
     */
    @Bean("dickTokenCache")
    public Cache<String, String>  dickTokenCache(){
        Cache<String, String> dickCache = persistentCacheManager.getCache("dickTokenCache", String.class, String.class);
        return dickCache;
    }



    /**
     * 用于本地缓存  eg: @Cacheable(value = "MIN10", keyGenerator = "simpleKeyGenerator")
     * @return
     */
    @Bean
    public  org.springframework.cache.CacheManager  jCacheCacheManager() {

        Map<String, CacheConfiguration<?, ?>> cacheMap = new HashMap<>();
        cacheMap.put("SEC30", getCacheConfigurationWithTtl(Duration.ofSeconds(30)).build());
        cacheMap.put("MIN5", getCacheConfigurationWithTtl(Duration.ofMillis(5)).build());

        EhcacheCachingProvider ehcacheCachingProvider = (EhcacheCachingProvider) Caching.getCachingProvider(EhcacheCachingProvider.class.getName());
        DefaultConfiguration defaultConfiguration = new DefaultConfiguration(cacheMap, ehcacheCachingProvider.getDefaultClassLoader());
        javax.cache.CacheManager cacheManager = ehcacheCachingProvider.getCacheManager(ehcacheCachingProvider.getDefaultURI(), defaultConfiguration);
        JCacheCacheManager jCacheCacheManager = new JCacheCacheManager(cacheManager);
        return  jCacheCacheManager;
    }

    /**
     * 优先内存
     * @param duration
     * @return
     */
    private  CacheConfigurationBuilder<String, Object> getCacheConfigurationWithTtl(Duration duration){
        CacheConfigurationBuilder<String, Object> cacheConfigurationBuilder = CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, Object.class,
                        ResourcePoolsBuilder.newResourcePoolsBuilder()
                                .heap(1000, EntryUnit.ENTRIES) // 最大存储1000条记录
                                .offheap(100, MemoryUnit.MB) )
                 .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(duration)) // ttl  Duration.ofSeconds(20)
//               .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofHours(3)))  TTI是指缓存项从最后一次访问到过期的时间间隔。

                .withEvictionAdvisor((key, value) -> false);
        return cacheConfigurationBuilder;
    }




    @Bean
    public KeyGenerator simpleKeyGenerator() {
        return (o, method, objects) -> {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(o.getClass().getSimpleName());
            stringBuilder.append(".");
            stringBuilder.append(method.getName());
            stringBuilder.append("[");
            for (Object obj :objects) {
                //可以把参数拼接后Md5
                stringBuilder.append( JSON.toJSONString(obj)+"");
            }
            stringBuilder.append("]");
            return stringBuilder.toString();
        };
    }

}

 

posted on 2024-10-24 18:28  lshan  阅读(69)  评论(0编辑  收藏  举报