[JavaWeb] SpringBoot + EhCache 通过代码形式进行增删缓存

 

前言:

SpringBoot使用的本地缓存,我查的Baidu大部分都是采用 注解形式来解决了。极少部分是采用 代码形式进行管理缓存。

注解的形式也无法更改 缓存的过期时间。本文采用 Element类进行更改过期时间。

本文支持 缓存持久化。会把缓存更新到磁盘 重启项目缓存也会生效。

 

引入pom依赖:

 1 <!-- cache -->
 2 <dependency>
 3     <groupId>org.springframework.boot</groupId>
 4     <artifactId>spring-boot-starter-cache</artifactId>
 5 </dependency>
 6 <!-- ehcache缓存 -->
 7 <dependency>
 8     <groupId>net.sf.ehcache</groupId>
 9     <artifactId>ehcache</artifactId>
10 </dependency>

 

编写ehcache.xml:

 1 <ehcache updateCheck="false" dynamicConfig="true">
 2 
 3     <!--表示当前系统临时目录-->
 4     <diskStore path="java.io.tmpdir/ehcache"/>
 5 
 6     <!--
 7     name:缓存名称。
 8     maxElementsInMemory:缓存最大个数。
 9     eternal:对象是否永久有效,一但设置了,timeout将不起作用。
10     timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
11     timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
12     overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
13     diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
14     maxElementsOnDisk:硬盘最大缓存个数。
15     diskPersistent:是否缓存虚拟机重启期数据WhetherthediskstorepersistsbetweenrestartsoftheVirtualMachine.Thedefaultvalueisfalse.
16     diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
17     memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
18     clearOnFlush:内存数量最大时是否清除。
19     -->
20 
21     <defaultCache
22             maxElementsInMemory="1"
23             eternal="false"
24             timeToIdleSeconds="120"
25             timeToLiveSeconds="120"
26             overflowToDisk="true"
27             diskPersistent="true"
28             memoryStoreEvictionPolicy="LRU"/>
29 
30     <cache
31         name="xiwiCacheManager"
32         maxElementsInMemory="1"
33         eternal="false"
34         timeToIdleSeconds="120"
35         timeToLiveSeconds="120"
36         overflowToDisk="true"
37         diskPersistent="true"
38         clearOnFlush="false"
39         maxElementsOnDisk="10000000"
40         diskExpiryThreadIntervalSeconds="120"
41         memoryStoreEvictionPolicy="LRU">
42         <bootstrapCacheLoaderFactory class="net.sf.ehcache.store.DiskStoreBootstrapCacheLoaderFactory" properties="bootstrapAsynchronously=true" />
43     </cache>
44 
45 </ehcache>

 

编写EhcacheConfig配置类:

 1 package com.xiwi.ehcache.common.config;
 2 
 3 import org.springframework.cache.ehcache.EhCacheCacheManager;
 4 import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
 5 import org.springframework.context.annotation.Bean;
 6 import org.springframework.context.annotation.Configuration;
 7 import org.springframework.core.io.ClassPathResource;
 8 
 9 /**
10  * file: EhcacheConfig
11  * date: 2020-10-15
12  * time: 8:52
13  * explain: Ehcache配置类
14  * author: Xiwi
15  */
16 @Configuration
17 public class EhcacheConfig {
18 
19     @Bean
20     public EhCacheCacheManager ehCacheCacheManager(EhCacheManagerFactoryBean bean){
21         if (bean.getObject() == null) { return null; }
22         return new EhCacheCacheManager(bean.getObject());
23     }
24 
25     @Bean
26     public EhCacheManagerFactoryBean ehCacheManagerFactoryBean(){
27         EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean ();
28         cacheManagerFactoryBean.setConfigLocation (new ClassPathResource("ehcache.xml"));
29         cacheManagerFactoryBean.setShared(true);
30         return cacheManagerFactoryBean;
31     }
32 }

 

编写EhcacheUtil类:

  1 package com.xiwi.ehcache.common.utils;
  2 
  3 import net.sf.ehcache.Cache;
  4 import net.sf.ehcache.CacheManager;
  5 import net.sf.ehcache.Element;
  6 import org.slf4j.Logger;
  7 import org.slf4j.LoggerFactory;
  8 import org.springframework.core.io.ClassPathResource;
  9 import org.springframework.stereotype.Component;
 10 import org.springframework.util.CollectionUtils;
 11 
 12 import javax.annotation.PostConstruct;
 13 import javax.annotation.Resource;
 14 import java.io.Serializable;
 15 import java.util.ArrayList;
 16 import java.util.LinkedHashMap;
 17 import java.util.List;
 18 import java.util.Map;
 19 
 20 /**
 21  * file: EhcacheUtil
 22  * date: 2020-10-15
 23  * time: 8:51
 24  * explain: Ehcache工具类
 25  * author: Xiwi
 26  */
 27 @Component
 28 public class EhcacheUtil {
 29 
 30     private final Logger logger = LoggerFactory.getLogger(EhcacheUtil.class);
 31 
 32     private String cacheManagerName = "xiwiCacheManager";
 33     private Integer MAX_ELEMENTS_IN_MEMORY = 5000; // 内存中最大缓存对象数
 34     private boolean OVERFLOW_TO_DISK = true; // 当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中
 35     @Resource
 36     private CacheManager cacheManager;
 37 
 38     public String getCacheManagerName() {
 39         return cacheManagerName;
 40     }
 41     public void setCacheManagerName(String cacheManagerName) {
 42         this.cacheManagerName = cacheManagerName;
 43 
 44     }
 45 
 46     @PostConstruct
 47     private void init() {
 48         System.setProperty("net.sf.ehcache.enableShutdownHook","true");
 49     }
 50 
 51     /**
 52      * 获取缓存
 53      * @param key
 54      * @return
 55      */
 56     public Object get(String key) {
 57         try {
 58             return getObject(key).getObjectValue();
 59         }catch (Exception e) {
 60             e.printStackTrace();
 61             return null;
 62         }
 63     }
 64 
 65     /**
 66      * 获取缓存
 67      * @param key
 68      * @param clazz 根据某一类型 进行强转
 69      * @param <T>
 70      * @return
 71      */
 72     public <T> T get(String key, Class<T> clazz) {
 73         try {
 74             return clazz.cast(getObject(key).getObjectValue());
 75         }catch (Exception e) {
 76             e.printStackTrace();
 77             return null;
 78         }
 79     }
 80 
 81     /**
 82      * 设置缓存
 83      * @param key
 84      * @param value
 85      * @return
 86      */
 87     public boolean set(String key, Object value) {
 88         try {
 89             getCache().put(new Element(key, value));
 90             shutdown();
 91             return true;
 92         }catch (Exception e) {
 93             e.printStackTrace();
 94             return false;
 95         }
 96     }
 97 
 98     /**
 99      * 设置缓存 (element级别上设置过期时间)
100      * @param key
101      * @param value
102      * @param time
103      * @return
104      */
105     public boolean set(String key, Object value, int time) {
106         try {
107             Element element = new Element(key, value);
108             element.setEternal(true);
109             element.setTimeToIdle(time); // 空闲时间
110             element.setTimeToLive(time); // 生存时间
111             getCache().put(element);
112             shutdown();
113             return true;
114         }catch (Exception e) {
115             e.printStackTrace();
116             return false;
117         }
118     }
119 
120     /**
121      * 删除缓存
122      * @param key 可以传一个值 或多个
123      * @return
124      */
125     public boolean del(String... key) {
126         try {
127             if (key != null && key.length > 0) {
128                 if (key.length == 1) {
129                     getCache().remove(key);
130                 } else {
131                     getCache().remove(CollectionUtils.arrayToList(key));
132                 }
133             }
134             shutdown();
135             return true;
136         }catch (Exception e) {
137             e.printStackTrace();
138             return false;
139         }
140     }
141 
142     /**
143      * 根据key 获取过期时间
144      * @param key
145      * @return 时间戳
146      */
147     public Long getExpire(String key) {
148         return getObject(key).getExpirationTime();
149     }
150 
151     /**
152      * 判断key是否存在
153      * @param key
154      * @return  true存在 false不存在
155      */
156     public boolean hasKey(String key) {
157         return getObject(key)!=null ? true : false;
158     }
159 
160     /**
161      * 递增
162      * @param key
163      * @param delta
164      * @return
165      */
166     public boolean incr(String key, Long delta) {
167         try {
168             if (delta < 0) {
169                 throw new RuntimeException("递增因子必须大于0");
170             }
171 
172             Element element = getObject(key);
173             long data = element==null ? 0L : getValueToLong(key);
174             data = data + delta;
175             this.cr(key, data, element);
176             shutdown();
177             return true;
178         }catch (Exception e){
179             e.printStackTrace();
180             return false;
181         }
182     }
183 
184     /**
185      * 递减
186      * @param key
187      * @param delta
188      * @return
189      */
190     public boolean decr(String key, Long delta) {
191         try {
192             if (delta < 0) {
193                 throw new RuntimeException("递减因子必须大于0");
194             }
195             Element element = getObject(key);
196             long data = element==null ? 0L : getValueToLong(key);
197             data = data - delta;
198             this.cr(key, data, element);
199             shutdown();
200             return true;
201         }catch (Exception e){
202             e.printStackTrace();
203             return false;
204         }
205     }
206 
207     /**
208      * 获取缓存域中的所有键值对
209      * @return
210      */
211     public List<Map<String, Object>> iterator() {
212         Cache cache = getCache();
213         List<Map<String, Object>> jsonResult = new ArrayList<>();
214         if (cache != null) {
215             cache.getAll(cache.getKeys()).forEach((key, value) -> {
216                 jsonResult.add(new LinkedHashMap<String, Object>() {{
217                     put("key", value.getObjectKey());
218                     put("value", value.getObjectValue());
219                     put("creation_time", value.getCreationTime());
220                     put("expiration_time", value.getExpirationTime());
221                     put("hit_count", value.getHitCount());
222                     put("last_access_time", value.getLastAccessTime());
223                     put("last_update_time", value.getLastUpdateTime());
224                     put("time_to_idle", value.getTimeToIdle());
225                     put("time_to_live", value.getTimeToLive());
226                     put("version", value.getVersion());
227                     put("is_eternal", value.isEternal());
228                 }});
229             });
230         }
231 //        shutdown();
232         return jsonResult;
233     }
234 
235     private Cache getCache() {
236         try {
237             /*if (!Arrays.asList(cacheManager.getCacheNames()).contains(cacheManagerName)) {
238                 System.out.println("Cache: " + cacheManagerName + "为空,正在建立一个缓存实例...");
239                 *//*Cache cache = new Cache(
240                         cacheManagerName,
241                         OVERFLOW_TO_DISK ? 1 : MAX_ELEMENTS_IN_MEMORY, // 如果为真: 只要有一个缓存元素,就直接存到硬盘上去
242                         OVERFLOW_TO_DISK,
243                         false,
244                         7200,
245                         3600);*//*
246 
247 //                DiskStoreConfiguration diskStoreConfiguration = new DiskStoreConfiguration();
248 //                diskStoreConfiguration.setPath("java.io.tmpdir/ehcache/test");
249 //                cacheManager.getConfiguration().addDiskStore(diskStoreConfiguration);
250                 Cache cache = cacheManager.getCache(cacheManagerName);
251                 CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
252 //                cacheConfiguration.setName(cacheManagerName);
253 //                cacheConfiguration.setMaxEntriesLocalHeap(OVERFLOW_TO_DISK ? 1 : MAX_ELEMENTS_IN_MEMORY);
254 //                cacheConfiguration.setOverflowToDisk(OVERFLOW_TO_DISK);
255                 cacheConfiguration.setDiskPersistent(true);
256                 cacheConfiguration.setEternal(false);
257                 cacheConfiguration.setTimeToLiveSeconds(7200);
258                 cacheConfiguration.setTimeToIdleSeconds(3600);
259                 cacheConfiguration.setMemoryStoreEvictionPolicy("LRU");
260 //                cacheConfiguration.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALRESTARTABLE)).maxEntriesLocalDisk(0);
261 
262                 cacheManager.addCache(cache);
263             }*/
264 
265             if(cacheManager == null || cacheManager.getStatus().intValue() != 1){
266                 cacheManager = new CacheManager(new ClassPathResource("ehcache.xml").getInputStream());
267             }
268 
269             return cacheManager.getCache(cacheManagerName);
270         }catch (Exception e) {
271             e.printStackTrace();
272             return null;
273         }
274     }
275     private Element getObject(String key) {
276         try {
277             return getCache().get(key);
278         }catch (Exception e) {
279 //            e.printStackTrace();
280             return null;
281         }
282     }
283     private boolean cr(String key, Long data, Element element) {
284         try {
285             Element newElement = new Element(key, data);
286             if (element != null) {
287                 newElement.setEternal(element.isEternal());
288                 newElement.setTimeToLive(element.getTimeToLive());
289                 newElement.setTimeToIdle(element.getTimeToLive());
290                 newElement.setVersion(element.getVersion());
291             }
292             getCache().put(newElement);
293             shutdown();
294             return true;
295         }catch (Exception e){
296 //            e.printStackTrace();
297             return false;
298         }
299     }
300     private Long getValueToLong(String key) {
301         try {
302             return Long.valueOf(String.valueOf(getObject(key).getObjectValue()));
303         }catch (Exception e) {
304 //            e.printStackTrace();
305             return 0L;
306         }
307     }
308     private void shutdown() {
309         if (OVERFLOW_TO_DISK) {
310             getCache().flush();
311 //            cacheManager.shutdown();
312         }
313     }
314 }

 

编写测试 Controller类:

 1 package com.xiwi.ehcache.controller;
 2 
 3 import com.xiwi.ehcache.common.utils.EhcacheUtil;
 4 import com.xiwi.ehcache.common.utils.User;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.web.bind.annotation.GetMapping;
 7 import org.springframework.web.bind.annotation.PathVariable;
 8 import org.springframework.web.bind.annotation.RestController;
 9 
10 import java.util.ArrayList;
11 import java.util.List;
12 
13 /**
14  * file: IndexController
15  * date: 2020-10-19
16  * time: 14:48
17  * explain: Ehcache测试控制层
18  * author: Xiwi
19  */
20 @RestController
21 public class IndexController {
22 
23     @Autowired
24     EhcacheUtil ehcacheUtil;
25 
26     @GetMapping("/setList/{key}/{time}")
27     public String set(
28             @PathVariable("key") String key,
29             @PathVariable("time") Integer time
30     ) {
31         List<User> list = new ArrayList<>();
32         list.add(new User(1, "name01", 11));
33         list.add(new User(2, "name02", 12));
34         list.add(new User(3, "name03", 13));
35         list.add(new User(4, "name04", 4));
36         System.out.println("list.size(): " + list.size());
37         ehcacheUtil.set(key, list, time);
38         return "setList ok";
39     }
40 
41     @GetMapping("/set/{key}/{value}/{time}")
42     public String set(
43             @PathVariable("key") String key,
44             @PathVariable("value") String value,
45             @PathVariable("time") Integer time
46     ) {
47         ehcacheUtil.set(key, value, time);
48         return "ok";
49     }
50 
51 
52     @GetMapping("/get/{key}")
53     public Object get(
54             @PathVariable("key") String key
55     ) {
56         return ehcacheUtil.get(key);
57     }
58 
59     @GetMapping("/getCache")
60     public Object getCache() {
61         return ehcacheUtil.iterator();
62     }
63 
64 
65     @GetMapping("/incr/{key}/{value}")
66     public Object incr(
67             @PathVariable("key") String key,
68             @PathVariable("value") Long value
69     ) {
70         ehcacheUtil.incr(key, value);
71         return ehcacheUtil.get(key);
72     }
73 
74     @GetMapping("/decr/{key}/{value}")
75     public Object decr(
76             @PathVariable("key") String key,
77             @PathVariable("value") Long value
78             ) {
79         ehcacheUtil.decr(key, value);
80         return ehcacheUtil.get(key);
81     }
82 
83     @GetMapping("/hasKey/{key}")
84     public boolean a(
85             @PathVariable("key") String key
86     ) {
87         return ehcacheUtil.hasKey(key);
88     }
89 }
posted @ 2020-10-21 10:14  Xiwi  阅读(442)  评论(0编辑  收藏  举报