Commit ab4a3aa5a16a124cf6f96ce237256958345d36de
1 parent
31c81ff7
#feat:增加CacheKeyGenerator
Showing
4 changed files
with
102 additions
and
28 deletions
README.md
pom.xml
| @@ -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 | } |