Spring接口缓存实现方案Caffeine和EhCache

Spring接口缓存实现方案Caffeine和EhCache

1.引入jar包
compile("com.github.ben-manes.caffeine:caffeine:2.8.6")
compile("org.springframework.boot:spring-boot-starter-cache")

2.application.properties
##配置ehcache
spring.cache.ehcache.config = classpath:/ehcache.xml
spring.cache.type = ehcache

##配置caffeine 或者使用下面的配置类也可以。
#spring.cache.cache-names=USER3
#spring.cache.caffeine.spec=initialCapacity=50,maximumSize=500,expireAfterWrite=5s
#spring.cache.type=caffeine

3.配置文件ehcache

<ehcache updateCheck="false" name="configCache">
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            />

        <!--  配置自定义缓存
        maxElementsInMemory:缓存中允许创建的最大对象数
        eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。
        timeToIdleSeconds:缓存数据的钝化时间,也就是在一个元素消亡之前,
                两次访问时间的最大时间间隔值,这只能在元素不是永久驻留时有效,
                如果该值是 0 就意味着元素可以停顿无穷长的时间。
        timeToLiveSeconds:缓存数据的生存时间,也就是一个元素从构建到消亡的最大时间间隔值,
                这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。
        overflowToDisk:内存不足时,是否启用磁盘缓存。
        memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。-->

 	<cache name="sysConfigCache2"
        maxElementsInMemory="10000" 
        eternal="false"
        overflowToDisk="false" 
        timeToIdleSeconds="900" 
        timeToLiveSeconds="1800"
        memoryStoreEvictionPolicy="LFU" />
        

</ehcache>

4.配置类caffeine

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Configuration
public class CaffeineConfig {
    /**
     * 默认的超时时间
     */
    @Value("${caching.expire.duration:60}")
    private int duration;

    @Value("${caching.maximumSize:1000}")
    private int maximumSize;

    @Value("${caching.initialCapacity:50}")
    private int initialCapacity;

    @Bean
    public CacheManager cacheManager() {
        CaffeineCache cache = buildCache("USER2", duration);
        SimpleCacheManager manager = new SimpleCacheManager();
        manager.setCaches(Arrays.asList(cache));
        return manager;
    }

    private CaffeineCache buildCache(String name, int secondsToExpire) {
        return new CaffeineCache(name, Caffeine.newBuilder()
                .expireAfterWrite(secondsToExpire, TimeUnit.SECONDS)
                .maximumSize(maximumSize)
                .initialCapacity(initialCapacity)
                .build());
    }

}

5.caffeine演示

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/caffeine")
@lombok.extern.slf4j.Slf4j
public class CaffeineController {
    @Autowired
    private CaffeineService caffeineService;


    @GetMapping("/user/{id}")
    public String getUser(@PathVariable String id) {
        long start = System.currentTimeMillis();
        log.info("查询开始:" + start);
        String res = caffeineService.getUser(id);
        long end = System.currentTimeMillis();
        log.info("查询结束:" + end);
        log.info("查询耗时:" + (end - start));
        return res;
    }

    @GetMapping("/user2/{id}")
    public String getUser2(@PathVariable String id) {
        long start = System.currentTimeMillis();
        log.info("查询开始2:" + start);
        String res = caffeineService.getUser2(id);
        long end = System.currentTimeMillis();
        log.info("查询结束2:" + end);
        log.info("查询耗时2:" + (end - start));
        return res;
    }


    @GetMapping("/user/{id}/{name}")
    public String updateUser(@PathVariable String id, @PathVariable String name) {
        return caffeineService.updateUser(id, name);
    }

    @DeleteMapping("/user/{id}")
    public String delUser(@PathVariable String id) {
        return caffeineService.delUser(id);
    }
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@lombok.extern.slf4j.Slf4j
@Service
public class CaffeineService {

    public static Map<String, String> map = new HashMap<>();

    @Autowired
    CacheManager cacheManager;

    static {
        map.put("1", "zhangsan");
        map.put("2", "lisi");
        map.put("3", "wangwu");
    }

    @Cacheable(value = "USER3", key = "#id")
    public String getUser(String id) {
        System.out.println("getUser() run......");
        log.info("getUser() run......");

        // 这是在使用注解时做的调试,每次都进来这里,说明缓存没有生效。
        if (null != cacheManager.getCache("USER3").get(id)) {
            Object common = cacheManager.getCache("USER3").get(id).get();
            log.warn("cache !!!============ {}", common);
            System.out.println("cache !!!============");
        } else {
            log.warn("no cache !!!============");
            System.out.println("no cache !!!============");
        }

        return map.get(id);
    }

    /**
     * 手动写, 更加有优势,注解方式的话,如果key删除了,就没有返回数据,不会重新从数据库中获取初始化。
     * @param id
     * @return
     */
    public String getUser2(String id) {
        System.out.println("getUser() run......");
        String cacheKey = id;
        Cache cache = cacheManager.getCache("USER3");
        String user = (String) Optional.ofNullable(cache)
                .map(c -> c.get(cacheKey))
                .map(wapper -> {
                    Object o = wapper.get();
                    System.out.println("fetch.................");
                    log.info("fetch user from cache: cacheKey: {}, String: {}", cacheKey, o);
                    return o;
                }).orElseGet(() -> {
                    String response = map.get(id);
                    return Optional.ofNullable(response)
                            .map(data -> {
                                cache.put(cacheKey, data);
                                log.info("put init user from cache: id: {}, String: {}", cacheKey, data);
                                System.out.println("put init .................");
                                return data;
                            }).orElse(null);
                });
        return user;
    }


    @CachePut(value = "USER3", key = "#id")
    public String updateUser(String id, String name) {
        log.info("updateUser() run......");
        map.put(id, name);
        return map.get(id);
    }

    @CacheEvict(value = "USER3", key = "#id")
    public String delUser(String id) {
        log.info("delUser() run......");
        map.remove(id);
        return map.toString();
    }
}

访问
#查询
http://localhost:8080/caffeine/user/1
#查询2
http://localhost:8080/caffeine/user2/1
#修改
http://localhost:8080/caffeine/user/1/simayi
#删除
http://localhost:8080/caffeine/user/1

6.ehcache演示

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/ehcache")
@lombok.extern.slf4j.Slf4j
public class EhCacheController {
    @Autowired
    private EhCacheService ehCacheService;


    @GetMapping("/user/{id}")
    public String getUser(@PathVariable String id) {
        long start = System.currentTimeMillis();
        log.info("查询开始:" + start);
        String res = ehCacheService.getUser(id);
        long end = System.currentTimeMillis();
        log.info("查询结束:" + end);
        log.info("查询耗时:" + (end - start));
        return res;
    }

    @GetMapping("/user2/{id}")
    public String getUser2(@PathVariable String id) {
        long start = System.currentTimeMillis();
        log.info("查询开始2:" + start);
        String res = ehCacheService.getUser2(id);
        long end = System.currentTimeMillis();
        log.info("查询结束2:" + end);
        log.info("查询耗时2:" + (end - start));
        return res;
    }


    @GetMapping("/user/{id}/{name}")
    public String updateUser(@PathVariable String id, @PathVariable String name) {
        return ehCacheService.updateUser(id, name);
    }

    @DeleteMapping("/user/{id}")
    public String delUser(@PathVariable String id) {
        return ehCacheService.delUser(id);
    }
}




import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@lombok.extern.slf4j.Slf4j
@Service
public class EhCacheService {

    public static Map<String, String> map = new HashMap<>();

    @Autowired
    CacheManager cacheManager;

    static {
        map.put("1", "zhangsan22");
        map.put("2", "lisi22");
        map.put("3", "wangwu22");
    }

    @Cacheable(value = "sysConfigCache2", key = "#id")
    public String getUser(String id) {
        System.out.println("getUser() run......");
        log.info("getUser() run......");

        // 这是在使用注解时做的调试,每次都进来这里,说明缓存没有生效。
        if (null != cacheManager.getCache("sysConfigCache2").get(id)) {
            Object common = cacheManager.getCache("sysConfigCache2").get(id).get();
            log.info("cache !!!============ {}", common);
            System.out.println("cache !!!============");
        } else {
            log.warn("no cache !!!============");
            System.out.println("no cache !!!============");
        }

        return map.get(id);
    }

    /**
     * 手动写, 更加有优势,注解方式的话,如果key删除了,就没有返回数据,不会重新从数据库中获取初始化。
     * @param id
     * @return
     */
    public String getUser2(String id) {
        System.out.println("getUser() run......");
        String cacheKey = id;
        Cache cache = cacheManager.getCache("sysConfigCache2");
        String user = (String) Optional.ofNullable(cache)
                .map(c -> c.get(cacheKey))
                .map(wapper -> {
                    Object o = wapper.get();
                    System.out.println("fetch.................");
                    log.info("fetch user from cache: cacheKey: {}, String: {}", cacheKey, o);
                    return o;
                }).orElseGet(() -> {
                    String response = map.get(id);
                    return Optional.ofNullable(response)
                            .map(data -> {
                                cache.put(cacheKey, data);
                                log.info("put init user from cache: id: {}, String: {}", cacheKey, data);
                                System.out.println("put init .................");
                                return data;
                            }).orElse(null);
                });
        return user;
    }


    @CachePut(value = "sysConfigCache2", key = "#id")
    public String updateUser(String id, String name) {
        log.info("updateUser() run......");
        map.put(id, name);
        return map.get(id);
    }

    @CacheEvict(value = "sysConfigCache2", key = "#id")
    public String delUser(String id) {
        log.info("delUser() run......");
        map.remove(id);
        return map.toString();
    }
}

访问
#查询
http://localhost:8080/ehcache/user/1
#查询2
http://localhost:8080/ehcache/user2/1
#修改
http://localhost:8080/ehcache/user/1/zhugeliang
#删除
http://localhost:8080/ehcache/user/1

posted on 2024-11-20 19:20  oktokeep  阅读(140)  评论(0)    收藏  举报