SpringBoot配置Redis自定義過(guò)期時(shí)間操作
SpringBoot配置Redis自定義過(guò)期時(shí)間
Redis配置依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> <version>1.4.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.8.1.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
SpringBoot-Reids配置文件
package com.regs.tms.common.redis;
@Configuration @EnableCaching// 啟用緩存,這個(gè)注解很重要 @ConfigurationProperties(prefix = "spring.redis") @Data public class RedisCacheConfig extends CachingConfigurerSupport { private String host; private Integer port; private Integer database; private String password; @Bean("redisTemplate") public RedisTemplate redisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(factory); //使用Jackson2JsonRedisSerializer來(lái)序列化和反序列化redis的value值 Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); serializer.setObjectMapper(mapper); template.setValueSerializer(serializer); template.setHashValueSerializer(serializer); // 設(shè)置鍵(key)的序列化采用StringRedisSerializer。 template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); //打開事務(wù)支持 template.setEnableTransactionSupport(true); template.afterPropertiesSet(); return template; } @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) throws SQLException { //配置事務(wù)管理器 return new DataSourceTransactionManager(dataSource); } @Bean("stringRedisTemplate") public StringRedisTemplate stringRedisTemplate() { Integer port = this.port == null ? 6379 : this.port; JedisConnectionFactory jedis = new JedisConnectionFactory(); jedis.setHostName(host); jedis.setPort(port); if (StringUtils.isNotEmpty(password)) { jedis.setPassword(password); } if (database != null) { jedis.setDatabase(database); } else { jedis.setDatabase(0); } // 初始化連接pool jedis.afterPropertiesSet(); // 獲取連接template StringRedisTemplate temple = new StringRedisTemplate(); temple.setConnectionFactory(jedis); return temple; } }
自定義失效注解
package com.regs.tms.common.redis.annotation;
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.TYPE}) public @interface CacheDuration { //Sets the expire time (in seconds). public long duration() default 60; }
自定義失效配置
package com.regs.tms.common.redis.annotation;
/** * ExpireCacheManager,繼承自RedisCacheManager, * 用于對(duì)@CacheExpire解析及有效期的設(shè)置 */ public class RedisExpireCacheManager extends RedisCacheManager implements ApplicationContextAware, InitializingBean { private ApplicationContext applicationContext; public RedisExpireCacheManager(RedisTemplate redisTemplate) { super(redisTemplate); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } @Override public void afterPropertiesSet() { parseCacheExpire(applicationContext); } private void parseCacheExpire(ApplicationContext applicationContext) { final Map<String, Long> cacheExpires = new HashMap<>(16); //掃描有注解 String[] beanNames = applicationContext.getBeanNamesForAnnotation(Cacheable.class); for (String beanName : beanNames) { final Class clazz = applicationContext.getType(beanName); addCacheExpires(clazz, cacheExpires); } //設(shè)置有效期 super.setExpires(cacheExpires); } private void addCacheExpires(final Class clazz, final Map<String, Long> cacheExpires) { ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { @Override public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { ReflectionUtils.makeAccessible(method); //根據(jù)CacheExpire注解獲取時(shí)間 CacheExpire cacheExpire = findCacheExpire(clazz, method); if (cacheExpire != null) { Cacheable cacheable = findAnnotation(method, Cacheable.class); String[] cacheNames = isEmpty(cacheable.value()) ? new String[]{} : cacheable.value(); for (String cacheName : cacheNames) { cacheExpires.put(cacheName, cacheExpire.expire()); } } } }, new ReflectionUtils.MethodFilter() { @Override public boolean matches(Method method) { return null != findAnnotation(method, Cacheable.class); } }); } /** * CacheExpire標(biāo)注的有效期,優(yōu)先使用方法上標(biāo)注的有效期 * * @param clazz * @param method * @return */ private CacheExpire findCacheExpire(Class clazz, Method method) { CacheExpire methodCache = findAnnotation(method, CacheExpire.class); if (null != methodCache) { return methodCache; } CacheExpire classCache = findAnnotation(clazz, CacheExpire.class); if (null != classCache) { return classCache; } return null; } }
spring boot 使用redis 超時(shí)時(shí)間重新設(shè)置
如果要計(jì)算每24小時(shí)的下單量,
通常的做法是,取出舊值,進(jìn)行加一在設(shè)置回去,
但是這樣就出現(xiàn)了一個(gè)問(wèn)題
第二次設(shè)置值的時(shí)候,把超時(shí)時(shí)間重新設(shè)置成個(gè)24小時(shí)
這樣無(wú)疑的記錄24小時(shí)的數(shù)量是不準(zhǔn)確的
并且spring boot 中,默認(rèn)使用了spring 來(lái)操作redis ,使存在每個(gè)redis中的值,都會(huì)加前面加入一些東西
1) "\xac\xed\x00\x05t\x00\x0bREDISUALIST"
我們?cè)诓檎颐總€(gè)值的時(shí)候,并不知道在key前面需要加點(diǎn)什么.
所以我們必須要用keys 這個(gè)命令 ,來(lái)匹配 我們需要查找的key,來(lái)取第一個(gè)
然后我們用 ttl 命令 返回指定key的剩余時(shí)間 ,重新設(shè)置回去,而不是設(shè)置24小時(shí),這樣就實(shí)現(xiàn)了24小時(shí)累加一次
在redisService 中,增加一個(gè)方法
/** * 獲取指定key的剩余超時(shí)時(shí)間,key最好是唯一的,有特點(diǎn)的,最好不要匹配出多個(gè) 例子 *111 取出 "\xac\xed\x00\x05t\x00\x0b111" * 返回剩余秒數(shù) * @param key * @return * create by jcd */ public Long ttlByKey(@NotNull String key){ Set<byte[]> keys = redisTemplate.getConnectionFactory().getConnection().keys(key.getBytes()); byte[] bytes = keys.stream().findFirst().get(); Long ttl = redisTemplate.getConnectionFactory().getConnection().ttl(bytes); return ttl; }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis返回結(jié)果封裝map過(guò)程解析
這篇文章主要介紹了Mybatis返回結(jié)果封裝map過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09Java實(shí)現(xiàn)讀取和寫入properties文件
這篇文章主要介紹了Java實(shí)現(xiàn)讀取和寫入properties文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08Java8深入學(xué)習(xí)系列(二)函數(shù)式編程
函數(shù)式編程,這個(gè)詞語(yǔ)由兩個(gè)名詞構(gòu)成,函數(shù),編程。編程這個(gè)詞我就不用解釋了,大家都是做這個(gè)的。函數(shù),其實(shí)單獨(dú)抽離出來(lái)這個(gè)詞語(yǔ),也并不陌生,那二者組合后的到底是什么呢,下面這篇文章主要給大家介紹了關(guān)于Java8函數(shù)式編程的相關(guān)資料,需要的朋友可以參考下。2017-08-08SpringMVC中的ConversionServiceExposingInterceptor工具類解析
這篇文章主要介紹了SpringMVC中的ConversionServiceExposingInterceptor工具類解析,ConversionServiceExposingInterceptor是Spring MVC的一個(gè)HandlerInterceptor,用于向請(qǐng)求添加一個(gè)屬性,需要的朋友可以參考下2023-12-12java實(shí)現(xiàn)文件上傳、下載、圖片預(yù)覽
這篇文章主要介紹了java實(shí)現(xiàn)文件上傳、下載、圖片預(yù)覽,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01