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