Commit ab4a3aa5a16a124cf6f96ce237256958345d36de

Authored by ci-aliyun
1 parent 31c81ff7

#feat:增加CacheKeyGenerator

README.md
@@ -24,3 +24,6 @@ spring: @@ -24,3 +24,6 @@ spring:
24 pool: 24 pool:
25 max-wait: 1 25 max-wait: 1
26 ``` 26 ```
  27 +
  28 +### v1.2.1
  29 +- 增加了KeyGenerator实现类,实现类中使用className.methodName:params拼接成key
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 6
7 <groupId>com.irrigation</groupId> 7 <groupId>com.irrigation</groupId>
8 <artifactId>common-lib</artifactId> 8 <artifactId>common-lib</artifactId>
9 - <version>1.2.0</version> 9 + <version>1.2.1</version>
10 10
11 <properties> 11 <properties>
12 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 12 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
src/main/java/com/irrigation/icl/cache/core/CustomCacheKeyGenerator.java 0 → 100644
  1 +package com.irrigation.icl.cache.core;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.springframework.cache.interceptor.KeyGenerator;
  5 +import org.springframework.util.StringUtils;
  6 +
  7 +import java.lang.reflect.Method;
  8 +
  9 +/**
  10 + * @Author: boni
  11 + * @Date: 2018/9/4-下午3:20
  12 + */
  13 +@Slf4j
  14 +public class CustomCacheKeyGenerator implements KeyGenerator {
  15 + public static final int NO_PARAM_KEY = 0;
  16 +
  17 + @Override
  18 + public Object generate(Object target, Method method, Object... params) {
  19 + StringBuilder key = new StringBuilder();
  20 + key.append(target.getClass().getSimpleName()).append(".").append(method.getName()).append(":");
  21 + if (params.length == 0) {
  22 + return key.append(NO_PARAM_KEY).toString();
  23 + }
  24 + key.append(StringUtils.arrayToCommaDelimitedString(params));
  25 + //String finalKey = key.toString();
  26 + //log.debug("using cache key={}", finalKey);
  27 + return key.toString();
  28 + }
  29 +}
src/main/java/com/irrigation/icl/cache/core/LayeringCache.java
@@ -6,17 +6,18 @@ import net.sf.ehcache.CacheException; @@ -6,17 +6,18 @@ import net.sf.ehcache.CacheException;
6 import net.sf.ehcache.CacheManager; 6 import net.sf.ehcache.CacheManager;
7 import net.sf.ehcache.Ehcache; 7 import net.sf.ehcache.Ehcache;
8 import net.sf.ehcache.Element; 8 import net.sf.ehcache.Element;
9 -import net.sf.ehcache.config.CacheConfiguration;  
10 -import net.sf.ehcache.config.Configuration;  
11 -import net.sf.ehcache.config.DiskStoreConfiguration;  
12 -import net.sf.ehcache.config.PersistenceConfiguration; 9 +import net.sf.ehcache.config.*;
13 import net.sf.ehcache.store.MemoryStoreEvictionPolicy; 10 import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
  11 +import net.sf.ehcache.store.compound.ReadWriteCopyStrategy;
14 import org.springframework.cache.Cache; 12 import org.springframework.cache.Cache;
  13 +import org.springframework.cache.ehcache.EhCacheCacheManager;
  14 +import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
15 import org.springframework.cache.support.SimpleValueWrapper; 15 import org.springframework.cache.support.SimpleValueWrapper;
16 import org.springframework.data.redis.cache.RedisCache; 16 import org.springframework.data.redis.cache.RedisCache;
17 import org.springframework.data.redis.core.RedisOperations; 17 import org.springframework.data.redis.core.RedisOperations;
18 import org.springframework.util.StopWatch; 18 import org.springframework.util.StopWatch;
19 19
  20 +import java.io.Serializable;
20 import java.sql.Time; 21 import java.sql.Time;
21 import java.text.SimpleDateFormat; 22 import java.text.SimpleDateFormat;
22 import java.time.LocalDateTime; 23 import java.time.LocalDateTime;
@@ -83,7 +84,8 @@ public class LayeringCache extends RedisCache { @@ -83,7 +84,8 @@ public class LayeringCache extends RedisCache {
83 // 先更新1级然后再更新2级;允许短时间内的数据不一致 84 // 先更新1级然后再更新2级;允许短时间内的数据不一致
84 if (layerL1Enable) { 85 if (layerL1Enable) {
85 Ehcache ehCache = getL1Cache(super.getName()); 86 Ehcache ehCache = getL1Cache(super.getName());
86 - ehCache.put(new Element(key, value, false, layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds(), layeringCacheProperties.getCacheL1().getLocalTimeToLiveSeconds())); 87 + ehCache.put(new Element(key, value, false, layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds(), layeringCacheProperties.getCacheL1()
  88 + .getLocalTimeToLiveSeconds()));
87 layeringCacheManager.publishMessage(Command.set(this.ID, super.getName(), String.valueOf(key))); 89 layeringCacheManager.publishMessage(Command.set(this.ID, super.getName(), String.valueOf(key)));
88 } 90 }
89 super.put(key, value); 91 super.put(key, value);
@@ -106,7 +108,8 @@ public class LayeringCache extends RedisCache { @@ -106,7 +108,8 @@ public class LayeringCache extends RedisCache {
106 public Cache.ValueWrapper putIfAbsent(Object key, final Object value) { 108 public Cache.ValueWrapper putIfAbsent(Object key, final Object value) {
107 if (layerL1Enable) { 109 if (layerL1Enable) {
108 Ehcache ehCache = getL1Cache(super.getName()); 110 Ehcache ehCache = getL1Cache(super.getName());
109 - ehCache.putIfAbsent(new Element(key, value, false, layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds(), layeringCacheProperties.getCacheL1().getLocalTimeToLiveSeconds())); 111 + ehCache.putIfAbsent(new Element(key, value, false, layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds(), layeringCacheProperties
  112 + .getCacheL1().getLocalTimeToLiveSeconds()));
110 layeringCacheManager.publishMessage(Command.set(this.ID, super.getName(), String.valueOf(key))); 113 layeringCacheManager.publishMessage(Command.set(this.ID, super.getName(), String.valueOf(key)));
111 } 114 }
112 Cache.ValueWrapper wrapper = super.putIfAbsent(key, value); 115 Cache.ValueWrapper wrapper = super.putIfAbsent(key, value);
@@ -125,7 +128,8 @@ public class LayeringCache extends RedisCache { @@ -125,7 +128,8 @@ public class LayeringCache extends RedisCache {
125 Cache.ValueWrapper wrapper = super.get(command.getKey()); 128 Cache.ValueWrapper wrapper = super.get(command.getKey());
126 if (wrapper != null) { 129 if (wrapper != null) {
127 Ehcache ehCache = getL1Cache(super.getName()); 130 Ehcache ehCache = getL1Cache(super.getName());
128 - ehCache.put(new Element(command.getKey(), wrapper.get(), false, layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds(), layeringCacheProperties.getCacheL1().getLocalTimeToLiveSeconds())); 131 + ehCache.put(new Element(command.getKey(), wrapper.get(), false, layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds(),
  132 + layeringCacheProperties.getCacheL1().getLocalTimeToLiveSeconds()));
129 log.info("Update Cache L1 {} - {}", command.getKey(), wrapper.get()); 133 log.info("Update Cache L1 {} - {}", command.getKey(), wrapper.get());
130 } 134 }
131 break; 135 break;
@@ -142,9 +146,12 @@ public class LayeringCache extends RedisCache { @@ -142,9 +146,12 @@ public class LayeringCache extends RedisCache {
142 Future<Ehcache> future = this.layeringL1CacheContainer.get(name); 146 Future<Ehcache> future = this.layeringL1CacheContainer.get(name);
143 if (future == null) { 147 if (future == null) {
144 Callable<Ehcache> callable = () -> { 148 Callable<Ehcache> callable = () -> {
145 - Ehcache cache = layeringL1CacheManager.getEhcache(name); 149 + Ehcache cache = layeringL1CacheManager.getCache(name);
146 if (cache == null) { 150 if (cache == null) {
147 - layeringL1CacheManager.addCache(name); 151 + CacheConfiguration cacheConfiguration = getCacheConfiguration();
  152 + cacheConfiguration.setName(name);
  153 + Ehcache ehcache = new net.sf.ehcache.Cache(cacheConfiguration);
  154 + layeringL1CacheManager.addCache(ehcache);
148 cache = layeringL1CacheManager.getEhcache(name); 155 cache = layeringL1CacheManager.getEhcache(name);
149 } 156 }
150 return cache; 157 return cache;
@@ -165,12 +172,42 @@ public class LayeringCache extends RedisCache { @@ -165,12 +172,42 @@ public class LayeringCache extends RedisCache {
165 172
166 } 173 }
167 174
  175 +
168 private String getDate() { 176 private String getDate() {
169 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS"); 177 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
170 178
171 return simpleDateFormat.format(new Date()); 179 return simpleDateFormat.format(new Date());
172 } 180 }
173 181
  182 + private CacheConfiguration getCacheConfiguration() {
  183 + // Cache
  184 + CacheConfiguration cacheConfiguration = new CacheConfiguration();
  185 + cacheConfiguration.setEternal(false);
  186 +
  187 + PersistenceConfiguration persistenceConfiguration = new PersistenceConfiguration();
  188 + persistenceConfiguration.setStrategy(PersistenceConfiguration.Strategy.NONE.name());
  189 +
  190 + cacheConfiguration.persistence(persistenceConfiguration);
  191 + cacheConfiguration.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);
  192 + cacheConfiguration.setDiskExpiryThreadIntervalSeconds(layeringCacheProperties.getCacheL1().getLocalDiskExpiryThreadIntervalSeconds());
  193 + // 默认false,使用引用.设置为true,避免外部代码修改了缓存对象.造成EhCache的缓存对象也随之改变
  194 + // 但是设置为true后,将引起element的tti不自动刷新.如果直接新建element去覆盖原值.则本地ttl和远程ttl会产生一定的误差.
  195 + // 因此,使用时放弃手动覆盖方式刷新本地tti,当本地tti过期后,自动从Redis中再获取即可.
  196 + cacheConfiguration.copyOnRead(true);
  197 + cacheConfiguration.copyOnWrite(true);
  198 +
  199 +// CopyStrategyConfiguration copyStrategyConfiguration = new CopyStrategyConfiguration();
  200 +// copyStrategyConfiguration.setClass(MyCopyStrategy.class.getName());
  201 +// copyStrategyConfiguration.setCopyStrategyInstance(new MyCopyStrategy());
  202 +
  203 +// cacheConfiguration.addCopyStrategy(copyStrategyConfiguration);
  204 +
  205 + cacheConfiguration.setTimeToIdleSeconds(layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds());
  206 + cacheConfiguration.setTimeToLiveSeconds(layeringCacheProperties.getCacheL1().getLocalTimeToLiveSeconds());
  207 +
  208 + return cacheConfiguration;
  209 + }
  210 +
174 private void initEhcache() { 211 private void initEhcache() {
175 if (layerL1Enable) { 212 if (layerL1Enable) {
176 this.ID = layeringCacheProperties.getCacheL1().getKey() + "." + getDate(); 213 this.ID = layeringCacheProperties.getCacheL1().getKey() + "." + getDate();
@@ -192,30 +229,35 @@ public class LayeringCache extends RedisCache { @@ -192,30 +229,35 @@ public class LayeringCache extends RedisCache {
192 dsc.setPath(layeringCacheProperties.getCacheL1().getLocalStoreLocation() + this.ID); 229 dsc.setPath(layeringCacheProperties.getCacheL1().getLocalStoreLocation() + this.ID);
193 configuration.diskStore(dsc); 230 configuration.diskStore(dsc);
194 231
195 - PersistenceConfiguration persistenceConfiguration = new PersistenceConfiguration();  
196 - persistenceConfiguration.setStrategy(PersistenceConfiguration.Strategy.NONE.name());  
197 -  
198 - // Cache  
199 - CacheConfiguration cacheConfiguration = new CacheConfiguration();  
200 - cacheConfiguration.setEternal(false);  
201 -  
202 - cacheConfiguration.persistence(persistenceConfiguration);  
203 - cacheConfiguration.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);  
204 - cacheConfiguration.setDiskExpiryThreadIntervalSeconds(layeringCacheProperties.getCacheL1().getLocalDiskExpiryThreadIntervalSeconds());  
205 - // 默认false,使用引用.设置为true,避免外部代码修改了缓存对象.造成EhCache的缓存对象也随之改变  
206 - // 但是设置为true后,将引起element的tti不自动刷新.如果直接新建element去覆盖原值.则本地ttl和远程ttl会产生一定的误差.  
207 - // 因此,使用时放弃手动覆盖方式刷新本地tti,当本地tti过期后,自动从Redis中再获取即可.  
208 - cacheConfiguration.copyOnRead(true);  
209 - cacheConfiguration.copyOnWrite(true);  
210 -  
211 - cacheConfiguration.setTimeToIdleSeconds(layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds());  
212 - cacheConfiguration.setTimeToLiveSeconds(layeringCacheProperties.getCacheL1().getLocalTimeToLiveSeconds()); 232 + CacheConfiguration cacheConfiguration = getCacheConfiguration();
213 233
214 configuration.setDefaultCacheConfiguration(cacheConfiguration); 234 configuration.setDefaultCacheConfiguration(cacheConfiguration);
215 configuration.setDynamicConfig(false); 235 configuration.setDynamicConfig(false);
216 configuration.setUpdateCheck(false); 236 configuration.setUpdateCheck(false);
217 237
  238 +
218 layeringL1CacheManager = new CacheManager(configuration); 239 layeringL1CacheManager = new CacheManager(configuration);
219 } 240 }
220 } 241 }
  242 +
  243 + class MyCopyStrategy implements ReadWriteCopyStrategy<Element> {
  244 + @Override
  245 + public Element copyForWrite(Element value) {
  246 + if (value != null) {
  247 + Object temp = (Serializable) value.getObjectValue();
  248 + return new Element(value.getObjectKey(), temp);
  249 + }
  250 + return value;
  251 + }
  252 +
  253 + @Override
  254 + public Element copyForRead(Element storedValue) {
  255 + if (storedValue != null) {
  256 + Object temp = (Serializable) storedValue.getObjectValue();
  257 + return new Element(storedValue.getObjectKey(), temp);
  258 + }
  259 + return storedValue;
  260 +
  261 + }
  262 + }
221 } 263 }