Commit c01c0a10e5344eb093815a7998f4d47df722eda5

Authored by ci-aliyun
1 parent 8cc01016

feat:增加cache支持,并修改项目版本为1.2.0

.gitignore
... ... @@ -4,3 +4,5 @@
4 4 target/
5 5  
6 6 \.DS_Store
  7 +
  8 +*.iml
... ...
... ... @@ -6,11 +6,12 @@
6 6  
7 7 <groupId>com.irrigation</groupId>
8 8 <artifactId>common-lib</artifactId>
9   - <version>1.0-SNAPSHOT</version>
  9 + <version>1.2.0</version>
10 10  
11 11 <properties>
12 12 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
13 13 <java.version>1.8</java.version>
  14 + <spring-boot.version>1.5.10.RELEASE</spring-boot.version>
14 15 <swagger.version>2.7.0</swagger.version>
15 16 <lombok.version>1.16.20</lombok.version>
16 17 <commons-codec.version>1.11</commons-codec.version>
... ... @@ -19,6 +20,8 @@
19 20 <fastjson.version>1.2.46</fastjson.version>
20 21 <spring-web.version>4.3.14.RELEASE</spring-web.version>
21 22 <spring-security-core.version>4.2.4.RELEASE</spring-security-core.version>
  23 + <ehcache.version>2.6.11</ehcache.version>
  24 +
22 25 </properties>
23 26  
24 27  
... ... @@ -83,6 +86,36 @@
83 86 <version>${spring-security-core.version}</version>
84 87 <scope>provided</scope>
85 88 </dependency>
  89 + <dependency>
  90 + <groupId>net.sf.ehcache</groupId>
  91 + <artifactId>ehcache-core</artifactId>
  92 + <version>${ehcache.version}</version>
  93 + <exclusions>
  94 + <exclusion>
  95 + <groupId>org.slf4j</groupId>
  96 + <artifactId>slf4j-api</artifactId>
  97 + </exclusion>
  98 + </exclusions>
  99 + <!--<scope>provided</scope>-->
  100 + </dependency>
  101 + <dependency>
  102 + <groupId>org.springframework.boot</groupId>
  103 + <artifactId>spring-boot-starter-cache</artifactId>
  104 + <version>${spring-boot.version}</version>
  105 + <!--<scope>provided</scope>-->
  106 + </dependency>
  107 + <dependency>
  108 + <groupId>org.springframework.boot</groupId>
  109 + <artifactId>spring-boot-starter-data-redis</artifactId>
  110 + <version>${spring-boot.version}</version>
  111 + <!--<scope>provided</scope>-->
  112 + </dependency>
  113 + <dependency>
  114 + <groupId>org.springframework.boot</groupId>
  115 + <artifactId>spring-boot-configuration-processor</artifactId>
  116 + <version>${spring-boot.version}</version>
  117 + <!--<scope>provided</scope>-->
  118 + </dependency>
86 119  
87 120 </dependencies>
88 121 <build>
... ...
src/main/java/com/irrigation/icl/cache/Command.java 0 → 100644
  1 +package com.irrigation.icl.cache;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.io.Serializable;
  6 +
  7 +/**
  8 + * Command
  9 + */
  10 +@Data
  11 +public class Command implements Serializable {
  12 +
  13 + private static final long serialVersionUID = 7126530485423286910L;
  14 +
  15 + // 设置本地缓存
  16 + public final static byte OPT_SET = 0x01;
  17 + // 删除本地缓存Key
  18 + public final static byte OPT_DEL = 0x02;
  19 + // 删除本地缓存
  20 + public final static byte OPT_REM = 0x03;
  21 +
  22 + public byte oper;
  23 + public String name;
  24 + public String key;
  25 + public String src;
  26 +
  27 + public Command() {
  28 + }
  29 +
  30 + public Command(String src, byte oper, String name, String key) {
  31 + this.src = src;
  32 + this.oper = oper;
  33 + this.name = name;
  34 + this.key = key;
  35 + }
  36 +
  37 + /**
  38 + * 更新本地缓存
  39 + *
  40 + * @param cacheName
  41 + * @param key
  42 + * @return
  43 + */
  44 + public static Command set(String src, String cacheName, String key) {
  45 + return new Command(src, OPT_SET, cacheName, key);
  46 + }
  47 +
  48 + /**
  49 + * 删除本地缓存Key
  50 + *
  51 + * @param cacheName
  52 + * @param key
  53 + * @return
  54 + */
  55 + public static Command del(String src, String cacheName, String key) {
  56 + return new Command(src, OPT_DEL, cacheName, key);
  57 + }
  58 +
  59 + /**
  60 + * 删除本地缓存
  61 + *
  62 + * @param cacheName
  63 + * @return
  64 + */
  65 + public static Command rem(String src, String cacheName) {
  66 + return new Command(src, OPT_REM, cacheName, null);
  67 + }
  68 +}
0 69 \ No newline at end of file
... ...
src/main/java/com/irrigation/icl/cache/LayeringCacheAutoFactory.java 0 → 100644
  1 +package com.irrigation.icl.cache;
  2 +
  3 +import com.irrigation.icl.cache.config.CacheConfig;
  4 +import com.irrigation.icl.cache.core.LayeringCacheLoadCondition;
  5 +import com.irrigation.icl.cache.core.LayeringCacheManager;
  6 +import com.irrigation.icl.cache.core.LayeringCacheProperties;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.springframework.boot.autoconfigure.AutoConfigureAfter;
  9 +import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
  10 +import org.springframework.boot.context.properties.EnableConfigurationProperties;
  11 +import org.springframework.cache.CacheManager;
  12 +import org.springframework.context.annotation.Bean;
  13 +import org.springframework.context.annotation.Conditional;
  14 +import org.springframework.context.annotation.Configuration;
  15 +import org.springframework.data.redis.connection.Message;
  16 +import org.springframework.data.redis.connection.MessageListener;
  17 +import org.springframework.data.redis.connection.RedisConnectionFactory;
  18 +import org.springframework.data.redis.core.RedisTemplate;
  19 +import org.springframework.data.redis.listener.PatternTopic;
  20 +import org.springframework.data.redis.listener.RedisMessageListenerContainer;
  21 +import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
  22 +
  23 +/**
  24 + * @Author: boni
  25 + * @Date: 2018/8/24-下午2:37
  26 + */
  27 +@Configuration
  28 +@Conditional(LayeringCacheLoadCondition.class)
  29 +@EnableConfigurationProperties(LayeringCacheProperties.class)
  30 +@Slf4j
  31 +public class LayeringCacheAutoFactory {
  32 + @Bean
  33 + public LayeringCacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate,
  34 + LayeringCacheProperties layeringCacheProperties) {
  35 + LayeringCacheManager cacheManager = new LayeringCacheManager(redisTemplate, layeringCacheProperties);
  36 + cacheManager.setUsePrefix(true);
  37 + cacheManager.setDefaultExpiration(90);
  38 + return cacheManager;
  39 + }
  40 +
  41 + @Bean
  42 + RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
  43 + LayeringCacheProperties layeringCacheProperties,
  44 + MessageListenerAdapter listenerAdapter) {
  45 + RedisMessageListenerContainer container = new RedisMessageListenerContainer();
  46 + container.setConnectionFactory(connectionFactory);
  47 + container.addMessageListener(listenerAdapter, new PatternTopic(layeringCacheProperties.getCacheL1().getTopic()));
  48 +
  49 + return container;
  50 + }
  51 +
  52 + @Bean
  53 + LayeringCacheSyncCommandHandler layeringCacheSyncCommandHandler(CacheManager cacheManager) {
  54 + LayeringCacheSyncCommandHandler handler = new LayeringCacheSyncCommandHandler(cacheManager);
  55 + return handler;
  56 + }
  57 +
  58 + @Bean
  59 + MessageListenerAdapter listenerAdapter(LayeringCacheSyncCommandHandler handler,
  60 + RedisTemplate<Object, Object> redisTemplate) {
  61 +
  62 + return new MessageListenerAdapter(new MessageListener() {
  63 + @Override
  64 + public void onMessage(Message message, byte[] pattern) {
  65 + byte[] content = message.getBody();
  66 + if (content != null) {
  67 + Command command = (Command) redisTemplate.getValueSerializer().deserialize(content);
  68 + if (command != null) {
  69 + log.info(command.toString());
  70 + handler.handle(command);
  71 + }
  72 + }
  73 + }
  74 +
  75 + });
  76 + }
  77 +}
0 78 \ No newline at end of file
... ...
src/main/java/com/irrigation/icl/cache/LayeringCacheSyncCommandHandler.java 0 → 100644
  1 +package com.irrigation.icl.cache;
  2 +
  3 +import com.irrigation.icl.cache.core.LayeringCache;
  4 +import lombok.Getter;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.cache.CacheManager;
  7 +
  8 +/**
  9 + * @Author: boni
  10 + * @Date: 2018/8/29-下午5:44
  11 + */
  12 +@Slf4j
  13 +@Getter
  14 +public class LayeringCacheSyncCommandHandler {
  15 + CacheManager cacheManager;
  16 +
  17 + public LayeringCacheSyncCommandHandler(CacheManager cacheManager) {
  18 + this.cacheManager = cacheManager;
  19 + }
  20 +
  21 + public void handle(Command command) {
  22 + if (cacheManager != null) {
  23 + LayeringCache layeringCache = (LayeringCache) cacheManager.getCache(command.getName());
  24 + if (layeringCache == null) {
  25 + return;
  26 + }
  27 + layeringCache.updateL1Cache(command);
  28 + }
  29 + }
  30 +}
... ...
src/main/java/com/irrigation/icl/cache/config/CacheConfig.java 0 → 100644
  1 +package com.irrigation.icl.cache.config;
  2 +
  3 +import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
  4 +import org.springframework.boot.autoconfigure.AutoConfigureAfter;
  5 +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
  6 +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  7 +import org.springframework.context.annotation.Bean;
  8 +import org.springframework.context.annotation.Configuration;
  9 +import org.springframework.data.redis.connection.RedisConnectionFactory;
  10 +import org.springframework.data.redis.core.RedisTemplate;
  11 +import org.springframework.data.redis.serializer.StringRedisSerializer;
  12 +
  13 +/**
  14 + * @Author: boni
  15 + * @Date: 2018/8/24-下午2:03
  16 + */
  17 +@Configuration
  18 +public class CacheConfig {
  19 +
  20 + @Bean
  21 + public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
  22 + RedisTemplate<Object, Object> template = new RedisTemplate<>();
  23 + template.setConnectionFactory(connectionFactory);
  24 +
  25 + //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
  26 +// Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
  27 +
  28 + GenericFastJsonRedisSerializer serializer = new GenericFastJsonRedisSerializer();
  29 +
  30 +// ObjectMapper mapper = new ObjectMapper();
  31 +// mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  32 +// mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  33 +// serializer.setObjectMapper(mapper);
  34 +
  35 + template.setValueSerializer(serializer);
  36 + //使用StringRedisSerializer来序列化和反序列化redis的key值
  37 + template.setKeySerializer(new StringRedisSerializer());
  38 + template.afterPropertiesSet();
  39 + return template;
  40 + }
  41 +
  42 +
  43 +}
... ...
src/main/java/com/irrigation/icl/cache/core/LayeringCache.java 0 → 100644
  1 +package com.irrigation.icl.cache.core;
  2 +
  3 +import com.irrigation.icl.cache.Command;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import net.sf.ehcache.CacheException;
  6 +import net.sf.ehcache.CacheManager;
  7 +import net.sf.ehcache.Ehcache;
  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;
  13 +import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
  14 +import org.springframework.cache.Cache;
  15 +import org.springframework.cache.support.SimpleValueWrapper;
  16 +import org.springframework.data.redis.cache.RedisCache;
  17 +import org.springframework.data.redis.core.RedisOperations;
  18 +import org.springframework.util.StopWatch;
  19 +
  20 +import java.sql.Time;
  21 +import java.text.SimpleDateFormat;
  22 +import java.time.LocalDateTime;
  23 +import java.util.Date;
  24 +import java.util.concurrent.Callable;
  25 +import java.util.concurrent.ConcurrentHashMap;
  26 +import java.util.concurrent.Future;
  27 +import java.util.concurrent.FutureTask;
  28 +
  29 +/**
  30 + * @Author: boni
  31 + * @Date: 2018/8/24-下午2:27
  32 + */
  33 +@Slf4j
  34 +public class LayeringCache extends RedisCache {
  35 + private LayeringCacheProperties layeringCacheProperties;
  36 + private LayeringCacheManager layeringCacheManager;
  37 + private CacheManager layeringL1CacheManager;
  38 + private final ConcurrentHashMap<String, Future<Ehcache>> layeringL1CacheContainer = new ConcurrentHashMap<>();
  39 +
  40 + private boolean layerL1Enable;
  41 + private String ID;
  42 +// private String HOST;
  43 +// private String CACHE_STORE;
  44 +// private String CACHE_STORE_SYNC;
  45 +
  46 +
  47 + public LayeringCache(LayeringCacheManager layeringCacheManager, String name, byte[] prefix,
  48 + RedisOperations<? extends Object, ? extends Object> redisOperations, long expiration) {
  49 + super(name, prefix, redisOperations, expiration);
  50 + this.layeringCacheManager = layeringCacheManager;
  51 + this.layeringCacheProperties = layeringCacheManager.getLayeringCacheProperties();
  52 + this.layerL1Enable = layeringCacheProperties.getCacheL1().isEnable();
  53 + initEhcache();
  54 + }
  55 +
  56 + @Override
  57 + public Cache.ValueWrapper get(Object key) {
  58 + StopWatch stopWatch = new StopWatch();
  59 + stopWatch.start();
  60 + Ehcache ehCache = null;
  61 + if (layerL1Enable) {
  62 + ehCache = getL1Cache(super.getName());
  63 + Element value = ehCache.get(key);
  64 + if (value != null) {
  65 + log.info("Hit Cache L1 (ehcache) :{}={}", key, value);
  66 + return (value != null ? new SimpleValueWrapper(value.getObjectValue()) : null);
  67 + }
  68 + }
  69 + Cache.ValueWrapper wrapper = super.get(key);
  70 + if (layerL1Enable && ehCache != null && wrapper != null) {
  71 + ehCache.put(new Element(key, wrapper.get()));
  72 + log.info("Hit Cache L2 (redis) :{}={}", key, wrapper);
  73 + }
  74 + stopWatch.stop();
  75 + log.info("get use {} ms", stopWatch.getTotalTimeMillis());
  76 + return wrapper;
  77 + }
  78 +
  79 + @Override
  80 + public void put(final Object key, final Object value) {
  81 + StopWatch stopWatch = new StopWatch();
  82 + stopWatch.start();
  83 + // 先更新1级然后再更新2级;允许短时间内的数据不一致
  84 + if (layerL1Enable) {
  85 + Ehcache ehCache = getL1Cache(super.getName());
  86 + ehCache.put(new Element(key, value, false, layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds(), layeringCacheProperties.getCacheL1().getLocalTimeToLiveSeconds()));
  87 + layeringCacheManager.publishMessage(Command.set(this.ID, super.getName(), String.valueOf(key)));
  88 + }
  89 + super.put(key, value);
  90 + stopWatch.stop();
  91 + log.info("put use {} ms", stopWatch.getTotalTimeMillis());
  92 + }
  93 +
  94 + @Override
  95 + public void evict(Object key) {
  96 + // 先删除2级缓存,然后再删除1级缓存;
  97 + super.evict(key);
  98 + if (layerL1Enable) {
  99 + Ehcache ehCache = getL1Cache(super.getName());
  100 + ehCache.remove(key);
  101 + layeringCacheManager.publishMessage(Command.del(this.ID, super.getName(), String.valueOf(key)));
  102 + }
  103 + }
  104 +
  105 + @Override
  106 + public Cache.ValueWrapper putIfAbsent(Object key, final Object value) {
  107 + if (layerL1Enable) {
  108 + Ehcache ehCache = getL1Cache(super.getName());
  109 + ehCache.putIfAbsent(new Element(key, value, false, layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds(), layeringCacheProperties.getCacheL1().getLocalTimeToLiveSeconds()));
  110 + layeringCacheManager.publishMessage(Command.set(this.ID, super.getName(), String.valueOf(key)));
  111 + }
  112 + Cache.ValueWrapper wrapper = super.putIfAbsent(key, value);
  113 + return wrapper;
  114 + }
  115 +
  116 + public void updateL1Cache(Command command) {
  117 + if (layerL1Enable && command != null && !this.ID.equals(command.getSrc())) {
  118 + switch (command.getOper()) {
  119 + case Command.OPT_DEL:
  120 + case Command.OPT_REM:
  121 + getL1Cache(command.getName()).remove(command.getKey());
  122 + log.info("Clear Cache L1 {} - {}", command.getName(), command.getKey());
  123 + break;
  124 + case Command.OPT_SET:
  125 + Cache.ValueWrapper wrapper = super.get(command.getKey());
  126 + if (wrapper != null) {
  127 + Ehcache ehCache = getL1Cache(super.getName());
  128 + ehCache.put(new Element(command.getKey(), wrapper.get(), false, layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds(), layeringCacheProperties.getCacheL1().getLocalTimeToLiveSeconds()));
  129 + log.info("Update Cache L1 {} - {}", command.getKey(), wrapper.get());
  130 + }
  131 + break;
  132 + default:
  133 + break;
  134 + }
  135 + }
  136 + }
  137 +
  138 + /**
  139 + * 创建本地缓存
  140 + */
  141 + private Ehcache getL1Cache(final String name) {
  142 + Future<Ehcache> future = this.layeringL1CacheContainer.get(name);
  143 + if (future == null) {
  144 + Callable<Ehcache> callable = () -> {
  145 + Ehcache cache = layeringL1CacheManager.getEhcache(name);
  146 + if (cache == null) {
  147 + layeringL1CacheManager.addCache(name);
  148 + cache = layeringL1CacheManager.getEhcache(name);
  149 + }
  150 + return cache;
  151 + };
  152 + FutureTask<Ehcache> task = new FutureTask<>(callable);
  153 + future = this.layeringL1CacheContainer.putIfAbsent(name, task);
  154 + if (future == null) {
  155 + future = task;
  156 + task.run();
  157 + }
  158 + }
  159 + try {
  160 + return future.get();
  161 + } catch (Exception e) {
  162 + this.layeringL1CacheContainer.remove(name);
  163 + throw new CacheException(e);
  164 + }
  165 +
  166 + }
  167 +
  168 + private String getDate() {
  169 + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
  170 +
  171 + return simpleDateFormat.format(new Date());
  172 + }
  173 +
  174 + private void initEhcache() {
  175 + if (layerL1Enable) {
  176 + this.ID = layeringCacheProperties.getCacheL1().getKey() + "." + getDate();
  177 +// this.HOST = Utils.getLocalHostIP();
  178 +// this.CACHE_STORE = layeringCacheProperties.getCacheL1().getKey()
  179 +// + layeringCacheProperties.getCacheL1().getSeparator()
  180 +// + "cache"
  181 +// + layeringCacheProperties.getCacheL1().getSeparator()
  182 +// + "store";
  183 +// this.CACHE_STORE_SYNC = this.CACHE_STORE + layeringCacheProperties.getCacheL1().getSeparator() + "sync";
  184 +
  185 + Configuration configuration = new Configuration();
  186 + configuration.setName(this.ID);
  187 + configuration.setMaxBytesLocalHeap(layeringCacheProperties.getCacheL1().getLocalMaxBytesLocalHeap());
  188 + configuration.setMaxBytesLocalDisk(layeringCacheProperties.getCacheL1().getLocalMaxBytesLocalDisk());
  189 + // DiskStore
  190 + // 每次启动设置新的文件地址,以避免重启期间一级缓存未同步,以及单机多应用启动造成EhcacheManager重复的问题.
  191 + DiskStoreConfiguration dsc = new DiskStoreConfiguration();
  192 + dsc.setPath(layeringCacheProperties.getCacheL1().getLocalStoreLocation() + this.ID);
  193 + configuration.diskStore(dsc);
  194 +
  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());
  213 +
  214 + configuration.setDefaultCacheConfiguration(cacheConfiguration);
  215 + configuration.setDynamicConfig(false);
  216 + configuration.setUpdateCheck(false);
  217 +
  218 + layeringL1CacheManager = new CacheManager(configuration);
  219 + }
  220 + }
  221 +}
... ...
src/main/java/com/irrigation/icl/cache/core/LayeringCacheLoadCondition.java 0 → 100644
  1 +package com.irrigation.icl.cache.core;
  2 +
  3 +import org.springframework.boot.bind.RelaxedPropertyResolver;
  4 +import org.springframework.context.annotation.Condition;
  5 +import org.springframework.context.annotation.ConditionContext;
  6 +import org.springframework.core.type.AnnotatedTypeMetadata;
  7 +
  8 +/**
  9 + * @Author: boni
  10 + * @Date: 2018/8/24-下午2:52
  11 + */
  12 +public class LayeringCacheLoadCondition implements Condition {
  13 + @Override
  14 + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
  15 + RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
  16 + context.getEnvironment(), "springext.cache.");
  17 +
  18 + Boolean enable = resolver.getProperty("enable",Boolean.class);
  19 + if(enable == null){
  20 + return false;
  21 + }
  22 + return enable.booleanValue();
  23 +
  24 + }
  25 +}
... ...
src/main/java/com/irrigation/icl/cache/core/LayeringCacheManager.java 0 → 100644
  1 +package com.irrigation.icl.cache.core;
  2 +
  3 +import com.irrigation.icl.cache.Command;
  4 +import org.springframework.data.redis.cache.RedisCache;
  5 +import org.springframework.data.redis.cache.RedisCacheManager;
  6 +import org.springframework.data.redis.core.RedisOperations;
  7 +
  8 +/**
  9 + * @Author: boni
  10 + * @Date: 2018/8/24-下午2:29
  11 + */
  12 +public class LayeringCacheManager extends RedisCacheManager {
  13 +
  14 + private LayeringCacheProperties layeringCacheProperties;
  15 +
  16 + public LayeringCacheProperties getLayeringCacheProperties() {
  17 + return layeringCacheProperties;
  18 + }
  19 +
  20 + public void setLayeringCacheProperties(LayeringCacheProperties layeringCacheProperties) {
  21 + this.layeringCacheProperties = layeringCacheProperties;
  22 + }
  23 +
  24 + public LayeringCacheManager(RedisOperations redisOperations, LayeringCacheProperties layeringCacheProperties) {
  25 + super(redisOperations);
  26 + this.layeringCacheProperties = layeringCacheProperties;
  27 + }
  28 +
  29 + @SuppressWarnings("unchecked")
  30 + @Override
  31 + protected RedisCache createCache(String cacheName) {
  32 + long expiration = computeExpiration(cacheName);
  33 + return new LayeringCache(
  34 + this,
  35 + cacheName,
  36 + (this.isUsePrefix() ? this.getCachePrefix().prefix(cacheName) : null),
  37 + this.getRedisOperations(),
  38 + expiration);
  39 + }
  40 +
  41 +
  42 + //notify other redis clent to update L1
  43 + public void publishMessage(Command command) {
  44 + this.getRedisOperations().convertAndSend(this.getLayeringCacheProperties().getCacheL1().getTopic(), command);
  45 + }
  46 +
  47 +
  48 +}
... ...
src/main/java/com/irrigation/icl/cache/core/LayeringCacheProperties.java 0 → 100644
  1 +package com.irrigation.icl.cache.core;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.boot.context.properties.ConfigurationProperties;
  5 +
  6 +/**
  7 + * @Author: boni
  8 + * @Date: 2018/8/24-下午2:59
  9 + */
  10 +
  11 +@Data
  12 +@ConfigurationProperties(prefix = "springext.cache")
  13 +public class LayeringCacheProperties {
  14 +
  15 + /**
  16 + * L1缓存配置
  17 + */
  18 + private L1 cacheL1;
  19 + private boolean enable = true;
  20 +
  21 + @Data
  22 + // ehcache设置
  23 + public static class L1 {
  24 +
  25 + /**
  26 + * 是否启用L1缓存
  27 + */
  28 + private boolean enable = false;
  29 + /**
  30 + * 启用L1缓存后同步的topic
  31 + */
  32 + private String topic = "default_L1_sync_topic";
  33 +
  34 + /**
  35 + * cache中使用的key前缀
  36 + */
  37 + private String key = "L1";
  38 +
  39 + /**
  40 + * key分隔符
  41 + */
  42 + private String separator = ":";
  43 +
  44 + /**
  45 + * L1缓存存储磁盘位置
  46 + */
  47 + private String localStoreLocation = "./cache/";
  48 + /**
  49 + * 本地缓存最大内存大小
  50 + */
  51 + private String localMaxBytesLocalHeap = "128M";
  52 + /**
  53 + * 本地缓存最大磁盘大小
  54 + */
  55 + private String localMaxBytesLocalDisk = "1024M";
  56 +
  57 + /**
  58 + * 本地缓存过期时间,单位秒,默认10分钟
  59 + */
  60 + private int localTimeToLiveSeconds = 1 * 60;
  61 + private int localTimeToIdleSeconds = 0;
  62 + /**
  63 + * 本地缓存清理周期,单位秒,默认3分钟
  64 + */
  65 + private int localDiskExpiryThreadIntervalSeconds = 90;
  66 + }
  67 +}
... ...