redis+spring注解方式实现配置缓存时间过期
2017-06-28 20:17
645 查看
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最大连接数 -->
<property name="maxTotal" value="500" />
<!-- 最大空闲连接数 -->
<property name="maxIdle" value="30"></property>
<!-- 连接最小空闲时间 -->
<property name="minEvictableIdleTimeMillis" value="300000"></property>
<!-- 每次释放连接的最大数目 -->
<property name="numTestsPerEvictionRun" value="3"></property>
<!-- 释放连接的扫描间隔(毫秒) -->
<property name="timeBetweenEvictionRunsMillis" value="1800000"></property>
<!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
<property name="softMinEvictableIdleTimeMillis" value="10000" />
<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
<property name="maxWaitMillis" value="1500" />
<!-- 在获取连接的时候检查有效性, 默认false -->
<property name="testOnBorrow" value="true" />
<!-- 在空闲时检查有效性, 默认false -->
<property name="testWhileIdle" value="true" />
<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
<property name="blockWhenExhausted" value="false" />
</bean>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
<property name="poolConfig" ref="jedisPoolConfig"></property>
<property name="hostName" value="127.0.0.1"></property>
<property name="port" value="6379"></property>
<property name="timeout" value="15000"></property>
<property name="usePool" value="true"></property>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory"></property>
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
</property>
</bean>
<!-- 启用缓存注解功能,这个是必须的,否则注解不会生效,另外,该注解一定要声明在spring主配置文件中才会生效 -->
<cache:annotation-driven cache-manager="redisCacheManager" />
<bean id="redisCacheManager" class="com.douwong.manage.test.action.ExtendedRedisCacheManager">
<!-- <constructor-arg ref="redisTemplate" />
是否使用前缀 默认:是
<property name="usePrefix" value="true" />
<property name="defaultExpiration" value="3600" /> -->
<constructor-arg name="redisOperations" ref="redisTemplate"/>
<constructor-arg name="cacheNames">
<set>
<value>caiya_a</value>
<value>caiya_test</value>
<value>sampleCache1</value>
<value>memoryCache</value>
<value>scanCache</value>
<value>padIndexCache</value>
<value>sampleCache1</value>
<value>sampleCache1</value>
</set>
</constructor-arg>
<!-- 默认缓存名字 -->
<property name="defaultCacheName" value="caiya_a"/>
<!-- 是否在容器启动时初始化 -->
<property name="loadRemoteCachesOnStartup" value="true"/>
<!-- 是否使用前缀 -->
<property name="usePrefix" value="true"/>
<!-- 前缀命名,仅当usePrefix为true时才生效 -->
<property name="cachePrefix">
<bean class="org.springframework.data.redis.cache.DefaultRedisCachePrefix">
<constructor-arg name="delimiter" value=":"/>
</bean>
</property>
<!-- 缓存名字和有效期的分隔符 -->
<property name="separator" value="#"/>
<!-- 默认有效期1h -->
<property name="defaultExpiration" value="3600"/>
<!-- 多个缓存有效期,一般的单个工程可以省略此项 -->
<!-- <property name="expires">
<map>
<entry key="caiya_a" value="1800"/>
</map>
</property> -->
</bean>
package com.douwong.manage.test.action;
import java.util.Collection;
import java.util.Collections;
import java.util.regex.Pattern;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.cache.Cache;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCachePrefix;
import org.springframework.data.redis.core.RedisOperations;
//import lombok.extern.log4j.Log4j2;
/**
* 扩展redis缓存管理器
* <p>
* 重写 RedisCacheManager createCache 方法
* <p>
* 在缓存名字上添加过期时间表达式 如:cachename#60*60
* @author hbp
*/
public class ExtendedRedisCacheManager extends RedisCacheManager {
private static final Logger logger = Logger.getLogger(ExtendedRedisCacheManager.class);
private static final ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("JavaScript");
private static final Pattern pattern = Pattern.compile("[+\\-*/%]");
private String defaultCacheName;
private char separator = '#';
public ExtendedRedisCacheManager(RedisOperations redisOperations) {
this(redisOperations, Collections.<String>emptyList());
}
public ExtendedRedisCacheManager(RedisOperations redisOperations, Collection<String> cacheNames) {
super(redisOperations, cacheNames);
}
@Override
public Cache getCache(String name) {
// try to get cache by name
RedisCache cache = (RedisCache) super.getCache(name);
if (cache != null) {
return cache;
}
// there's no cache which has given name
// find separator in cache name
int index = name.lastIndexOf(getSeparator());
if (index < 0) {
return null;
}
// split name by the separator
String cacheName = name.substring(0, index);
if(StringUtils.isBlank(cacheName)){
cacheName = defaultCacheName;
}
cache = (RedisCache) super.getCache(cacheName);
if (cache == null) {
return null;
}
// get expiration from name
Long expiration = getExpiration(name, index);
if (expiration == null || expiration < 0) {
logger.warn("Default expiration time will be used for cache '{}' because cannot parse '{}', cacheName : " + cacheName + ", name : " + name);
return cache;
}
return new RedisCache(cacheName, (isUsePrefix() ? getCachePrefix().prefix(cacheName) : null), getRedisOperations(), expiration);
}
public char getSeparator() {
return separator;
}
/**
* Char that separates cache name and expiration time, default: #.
*
* @param separator
*/
public void setSeparator(char separator) {
this.separator = separator;
}
private Long getExpiration(final String name, final int separatorIndex) {
Long expiration = null;
String expirationAsString = name.substring(separatorIndex + 1);
try {
// calculate expiration, support arithmetic expressions.
if(pattern.matcher(expirationAsString).find()){
expiration = (long) Double.parseDouble(scriptEngine.eval(expirationAsString).toString());
}else{
expiration = Long.parseLong(expirationAsString);
}
} catch (NumberFormatException ex) {
logger.error(String.format("Cannnot separate expiration time from cache: '%s'", name), ex);
} catch (ScriptException e) {
logger.error(String.format("Cannnot separate expiration time from cache: '%s'", name), e);
}
return expiration;
}
@Override
public void setUsePrefix(boolean usePrefix) {
super.setUsePrefix(usePrefix);
}
@Override
public void setCachePrefix(RedisCachePrefix cachePrefix) {
super.setCachePrefix(cachePrefix);
}
public void setDefaultCacheName(String defaultCacheName) {
this.defaultCacheName = defaultCacheName;
}
}
注意:在引入相关jar包的时候,必须要用jedis_2.9.0.jar、spring-data-redis-1.6.0.RELEASE.jar,因为这些jar包的版本对整个项目影响很大的;
可以参考代码来源:https://my.oschina.net/wnjustdoit/blog/644311
<!-- 最大连接数 -->
<property name="maxTotal" value="500" />
<!-- 最大空闲连接数 -->
<property name="maxIdle" value="30"></property>
<!-- 连接最小空闲时间 -->
<property name="minEvictableIdleTimeMillis" value="300000"></property>
<!-- 每次释放连接的最大数目 -->
<property name="numTestsPerEvictionRun" value="3"></property>
<!-- 释放连接的扫描间隔(毫秒) -->
<property name="timeBetweenEvictionRunsMillis" value="1800000"></property>
<!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
<property name="softMinEvictableIdleTimeMillis" value="10000" />
<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
<property name="maxWaitMillis" value="1500" />
<!-- 在获取连接的时候检查有效性, 默认false -->
<property name="testOnBorrow" value="true" />
<!-- 在空闲时检查有效性, 默认false -->
<property name="testWhileIdle" value="true" />
<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
<property name="blockWhenExhausted" value="false" />
</bean>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
<property name="poolConfig" ref="jedisPoolConfig"></property>
<property name="hostName" value="127.0.0.1"></property>
<property name="port" value="6379"></property>
<property name="timeout" value="15000"></property>
<property name="usePool" value="true"></property>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory"></property>
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
</property>
</bean>
<!-- 启用缓存注解功能,这个是必须的,否则注解不会生效,另外,该注解一定要声明在spring主配置文件中才会生效 -->
<cache:annotation-driven cache-manager="redisCacheManager" />
<bean id="redisCacheManager" class="com.douwong.manage.test.action.ExtendedRedisCacheManager">
<!-- <constructor-arg ref="redisTemplate" />
是否使用前缀 默认:是
<property name="usePrefix" value="true" />
<property name="defaultExpiration" value="3600" /> -->
<constructor-arg name="redisOperations" ref="redisTemplate"/>
<constructor-arg name="cacheNames">
<set>
<value>caiya_a</value>
<value>caiya_test</value>
<value>sampleCache1</value>
<value>memoryCache</value>
<value>scanCache</value>
<value>padIndexCache</value>
<value>sampleCache1</value>
<value>sampleCache1</value>
</set>
</constructor-arg>
<!-- 默认缓存名字 -->
<property name="defaultCacheName" value="caiya_a"/>
<!-- 是否在容器启动时初始化 -->
<property name="loadRemoteCachesOnStartup" value="true"/>
<!-- 是否使用前缀 -->
<property name="usePrefix" value="true"/>
<!-- 前缀命名,仅当usePrefix为true时才生效 -->
<property name="cachePrefix">
<bean class="org.springframework.data.redis.cache.DefaultRedisCachePrefix">
<constructor-arg name="delimiter" value=":"/>
</bean>
</property>
<!-- 缓存名字和有效期的分隔符 -->
<property name="separator" value="#"/>
<!-- 默认有效期1h -->
<property name="defaultExpiration" value="3600"/>
<!-- 多个缓存有效期,一般的单个工程可以省略此项 -->
<!-- <property name="expires">
<map>
<entry key="caiya_a" value="1800"/>
</map>
</property> -->
</bean>
package com.douwong.manage.test.action;
import java.util.Collection;
import java.util.Collections;
import java.util.regex.Pattern;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.cache.Cache;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCachePrefix;
import org.springframework.data.redis.core.RedisOperations;
//import lombok.extern.log4j.Log4j2;
/**
* 扩展redis缓存管理器
* <p>
* 重写 RedisCacheManager createCache 方法
* <p>
* 在缓存名字上添加过期时间表达式 如:cachename#60*60
* @author hbp
*/
public class ExtendedRedisCacheManager extends RedisCacheManager {
private static final Logger logger = Logger.getLogger(ExtendedRedisCacheManager.class);
private static final ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("JavaScript");
private static final Pattern pattern = Pattern.compile("[+\\-*/%]");
private String defaultCacheName;
private char separator = '#';
public ExtendedRedisCacheManager(RedisOperations redisOperations) {
this(redisOperations, Collections.<String>emptyList());
}
public ExtendedRedisCacheManager(RedisOperations redisOperations, Collection<String> cacheNames) {
super(redisOperations, cacheNames);
}
@Override
public Cache getCache(String name) {
// try to get cache by name
RedisCache cache = (RedisCache) super.getCache(name);
if (cache != null) {
return cache;
}
// there's no cache which has given name
// find separator in cache name
int index = name.lastIndexOf(getSeparator());
if (index < 0) {
return null;
}
// split name by the separator
String cacheName = name.substring(0, index);
if(StringUtils.isBlank(cacheName)){
cacheName = defaultCacheName;
}
cache = (RedisCache) super.getCache(cacheName);
if (cache == null) {
return null;
}
// get expiration from name
Long expiration = getExpiration(name, index);
if (expiration == null || expiration < 0) {
logger.warn("Default expiration time will be used for cache '{}' because cannot parse '{}', cacheName : " + cacheName + ", name : " + name);
return cache;
}
return new RedisCache(cacheName, (isUsePrefix() ? getCachePrefix().prefix(cacheName) : null), getRedisOperations(), expiration);
}
public char getSeparator() {
return separator;
}
/**
* Char that separates cache name and expiration time, default: #.
*
* @param separator
*/
public void setSeparator(char separator) {
this.separator = separator;
}
private Long getExpiration(final String name, final int separatorIndex) {
Long expiration = null;
String expirationAsString = name.substring(separatorIndex + 1);
try {
// calculate expiration, support arithmetic expressions.
if(pattern.matcher(expirationAsString).find()){
expiration = (long) Double.parseDouble(scriptEngine.eval(expirationAsString).toString());
}else{
expiration = Long.parseLong(expirationAsString);
}
} catch (NumberFormatException ex) {
logger.error(String.format("Cannnot separate expiration time from cache: '%s'", name), ex);
} catch (ScriptException e) {
logger.error(String.format("Cannnot separate expiration time from cache: '%s'", name), e);
}
return expiration;
}
@Override
public void setUsePrefix(boolean usePrefix) {
super.setUsePrefix(usePrefix);
}
@Override
public void setCachePrefix(RedisCachePrefix cachePrefix) {
super.setCachePrefix(cachePrefix);
}
public void setDefaultCacheName(String defaultCacheName) {
this.defaultCacheName = defaultCacheName;
}
}
注意:在引入相关jar包的时候,必须要用jedis_2.9.0.jar、spring-data-redis-1.6.0.RELEASE.jar,因为这些jar包的版本对整个项目影响很大的;
可以参考代码来源:https://my.oschina.net/wnjustdoit/blog/644311
相关文章推荐
- Spring AOP如何整合redis(注解方式)实现缓存统一管理详解
- Spring AOP整合redis(注解方式) 实现缓存统一管理
- 原始方式:spring四种依赖注入方式 |注解方式:Spring零配置通过注解实现Bean依赖注入
- Spring整合Redis用作缓存-注解方式
- Spring实现AOP方式之二:使用注解配置 Spring AOP
- spring的事务管理(配置文件方式和注解方式实现、转账环境搭建)
- Spring-Session实现Session共享Redis集群方式配置教程
- spring4纯注解方式实现aop配置
- SpringMVC+Spring+mybatis+redis项目从零开始--redis缓存策略和配置实现
- Spring AOP基于注解的“零配置”方式实现以及一些其他知识点
- Spring的AOP分为注解和配置两种方式实现
- Spring Boot Cache + redis 设置有效时间和自动刷新缓存,时间支持在配置文件中配置
- Spring整理11 -- 面对切面(AOP)1 -- 注解配置的方式实现AOP
- Spring 管理hibernate事物,xml配置,注解 两种实现方式
- Spring整理11 -- 面对切面(AOP)1 -- 注解配置的方式实现AOP
- 注解方式配置Spring实现Ioc
- Spring Cache+Redis实现自定义注解缓存
- Spring + ehcache 缓存配置,注解实现
- SpringBoot注解缓存配置浅析(Redis集群)
- Spring AOP+注解的方式实现缓存的获取