【前置條件】
1.maven關鍵依賴:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
2.redis.properties文件配置:
# redis #
redis.cache.pool.maxTotal=100
redis.cache.pool.maxIdle=5
redis.cache.pool.maxWaitMillis=1000
redis.cache.pool.testOnBorrow=true
redis.cache.usePool=true
redis.cluster.password=
redis.cluster.timeout=6000
# redis cluster ip #
clusterHostAndPorts[0]=10.11.12.247:6380
clusterHostAndPorts[1]=10.11.12.247:6380
clusterHostAndPorts[2]=10.11.12.247:6380
clusterHostAndPorts[3]=10.11.12.247:6380
clusterHostAndPorts[4]=10.11.12.247:6380
clusterHostAndPorts[5]=10.11.12.247:6380
3.spring啓動注入類:
package com.bbs.redis.util;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class ApplicationContextBean implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public ApplicationContextBeans() {
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static Object getBean(String name) throws BeansException {
return applicationContext.getBean(name);
}
public static Object getBean(String name, Class<?> requiredType) throws BeansException {
return applicationContext.getBean(name, requiredType);
}
public static boolean containsBean(String name) {
return applicationContext.containsBean(name);
}
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return applicationContext.isSingleton(name);
}
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
return applicationContext.getType(name);
}
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
return applicationContext.getAliases(name);
}
public static <T> T getBean(Class<T> requiredType) throws BeansException {
return applicationContext.getBean(requiredType);
}
public static <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
return applicationContext.getBeansOfType(type);
}
}
4.SerializeUtil序列化類:
package com.bbs.redis.util.SerializeUtil;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
public class SerializeUtil implements RedisSerializer<Object> {
private static Log log = LogFactory.getLog(SerializeUtil.class);
public SerializeUtil() {
}
public byte[] serialize(Object object) throws SerializationException {
if (object == null) {
return null;
} else {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
byte[] var6 = bytes;
return var6;
} catch (Exception var18) {
log.info(var18.getMessage());
} finally {
try {
if (baos != null) {
baos.close();
}
} catch (IOException var17) {
log.info(var17.getMessage());
}
try {
if (oos != null) {
oos.close();
}
} catch (IOException var16) {
log.info(var16.getMessage());
}
}
return null;
}
}
public Object deserialize(byte[] bytes) throws SerializationException {
if (bytes == null) {
return null;
} else {
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
Object o = ois.readObject();
Object var6 = o;
return var6;
} catch (Exception var18) {
log.info(var18.getMessage());
} finally {
try {
if (ois != null) {
ois.close();
}
} catch (IOException var17) {
log.info(var17.getMessage());
}
try {
if (bais != null) {
bais.close();
}
} catch (IOException var16) {
log.info(var16.getMessage());
}
}
return null;
}
}
}
5.spring-redis.xml配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<!-- <beans xmlns="http://www.springframework.org/schema/beans" -->
<!-- xmlns:context="http://www.springframework.org/schema/context" -->
<!-- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -->
<!-- xsi:schemaLocation="http://www.springframework.org/schema/beans -->
<!-- http://www.springframework.org/schema/beans/spring-beans-4.0.xsd -->
<!-- http://www.springframework.org/schema/context -->
<!-- http://www.springframework.org/schema/context/spring-context-4.0.xsd"> -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<bean id="clusterConfigurationProperties" class="com.warlock.config.ClusterConfigurationProperties">
</bean>
<bean id="oldApplicationContext" class="com.bbs.redis.util.ApplicationContextBeans" ></bean>
<bean id="oldRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean class="com.bbs.redis.util.SerializeUtil" />
</property>
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
<bean id="oldStringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean class="com.bbs.redis.util.SerializeUtil" />
</property>
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
<bean id="jedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
<!-- <bean id="lettuceTemplate" class="org.springframework.data.redis.core.RedisTemplate"> -->
<!-- <property name="keySerializer"> -->
<!-- <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> -->
<!-- </property> -->
<!-- <property name="valueSerializer"> -->
<!-- <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /> -->
<!-- </property> -->
<!-- <property name="connectionFactory" ref="lettuceConnectionFactory" /> -->
<!-- </bean> -->
<!-- <bean id="lettuceConnectionFactory" class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"> -->
<!-- <property name="password" value="${redis.cluster.password}" /> -->
<!-- <property name="timeout" value="${redis.cluster.timeout}" /> -->
<!-- <constructor-arg ref="redisClusterConfiguration" /> -->
<!-- </bean> -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<!-- <property name="hostName" value="${redis.cache.ip}" /> -->
<!-- <property name="port" value="${redis.cache.port}" /> -->
<property name="usePool" value="#{conf['redis.cache.usePool']}" />
<!-- <property name="poolConfig" ref="jedisPoolConfig" /> -->
<property name="password" value="#{conf['redis.cluster.password']}" />
<property name="timeout" value="#{conf['redis.cluster.timeout']}" />
<constructor-arg ref="redisClusterConfiguration" />
<constructor-arg ref="jedisPoolConfig" />
</bean>
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="#{conf['redis.cache.pool.maxTotal']}" />
<property name="maxIdle" value="#{conf['redis.cache.pool.maxIdle']}" />
<property name="maxWaitMillis" value="#{conf['redis.cache.pool.maxWaitMillis']}" />
<property name="testOnBorrow" value="#{conf['redis.cache.pool.testOnBorrow']}" />
</bean>
<!-- <bean id="clusterRedisNodes1" class="org.springframework.data.redis.connection.RedisNode"> -->
<!-- <constructor-arg value="${redis.cluster.node1.ip}" /> -->
<!-- <constructor-arg value="${redis.cluster.node1.port}" type="int" /> -->
<!-- </bean> -->
<!-- <bean id="clusterRedisNodes2" class="org.springframework.data.redis.connection.RedisNode"> -->
<!-- <constructor-arg value="${redis.cluster.node2.ip}" /> -->
<!-- <constructor-arg value="${redis.cluster.node2.port}" type="int" /> -->
<!-- </bean> -->
<!-- <bean id="clusterRedisNodes3" class="org.springframework.data.redis.connection.RedisNode"> -->
<!-- <constructor-arg value="${redis.cluster.node3.ip}" /> -->
<!-- <constructor-arg value="${redis.cluster.node3.port}" type="int" /> -->
<!-- </bean> -->
<!-- <bean id="clusterRedisNodes4" class="org.springframework.data.redis.connection.RedisNode"> -->
<!-- <constructor-arg value="${redis.cluster.node4.ip}" /> -->
<!-- <constructor-arg value="${redis.cluster.node4.port}" type="int" /> -->
<!-- </bean> -->
<!-- <bean id="clusterRedisNodes5" class="org.springframework.data.redis.connection.RedisNode"> -->
<!-- <constructor-arg value="${redis.cluster.node5.ip}" /> -->
<!-- <constructor-arg value="${redis.cluster.node5.port}" type="int" /> -->
<!-- </bean> -->
<!-- <bean id="clusterRedisNodes6" class="org.springframework.data.redis.connection.RedisNode"> -->
<!-- <constructor-arg value="${redis.cluster.node6.ip}" /> -->
<!-- <constructor-arg value="${redis.cluster.node6.port}" type="int" /> -->
<!-- </bean> -->
<bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
<!-- spring4.X的玩法 -->
<!-- <property name="maxRedirects" value="3" /> -->
<!-- <property name="clusterNodes"> -->
<!-- <set> -->
<!-- <ref bean="clusterRedisNodes1" /> -->
<!-- <ref bean="clusterRedisNodes2" /> -->
<!-- <ref bean="clusterRedisNodes3" /> -->
<!-- <ref bean="clusterRedisNodes4" /> -->
<!-- <ref bean="clusterRedisNodes5" /> -->
<!-- <ref bean="clusterRedisNodes6" /> -->
<!-- </set> -->
<!-- </property> -->
<!-- <property name="propertySource" > -->
<!-- <props> -->
<!-- <prop key="spring.redis.cluster.nodes">10.11.24.38:7000,10.11.24.38:7001,10.11.24.38:7002,10.11.24.38:7003,10.11.24.38:7004,10.11.24.38:7005</prop> -->
<!-- <prop key="spring.redis.cluster.timeout">6000</prop> -->
<!-- <prop key="spring.redis.cluster.max-redirects">3</prop> -->
<!-- <prop key="spring.redis.cluster.password"></prop> -->
<!-- </props> -->
<!-- </property> -->
<!-- spring3的玩法 -->
<constructor-arg >
<set>
<value>#{conf['clusterHostAndPorts[0]']}</value>
<value>#{conf['clusterHostAndPorts[1]']}</value>
<value>#{conf['clusterHostAndPorts[2]']}</value>
<value>#{conf['clusterHostAndPorts[3]']}</value>
<value>#{conf['clusterHostAndPorts[4]']}</value>
<value>#{conf['clusterHostAndPorts[5]']}</value>
</set>
</constructor-arg>
<!-- <constructor-arg ref="props"/> -->
<!-- <constructor-arg> -->
<!-- <bean class="java.util.Set"> -->
<!-- <util:set> -->
<!-- <value>clusterHostAndPorts[0] = 10.11.24.38:7000</value> -->
<!-- <value>clusterHostAndPorts[1] = 10.11.24.38:7001</value> -->
<!-- <value>clusterHostAndPorts[2] = 10.11.24.38:7002</value> -->
<!-- <value>clusterHostAndPorts[3] = 10.11.24.38:7003</value> -->
<!-- <value>clusterHostAndPorts[4] = 10.11.24.38:7004</value> -->
<!-- <value>clusterHostAndPorts[5] = 10.11.24.38:7005</value> -->
<!-- </util:set> -->
<!-- </bean> -->
<!-- </constructor-arg> -->
<!-- <property name="clusterNodes"> -->
<!-- <util:set> -->
<!-- <value>clusterHostAndPorts[0] = 10.11.24.38:7000</value> -->
<!-- <value>clusterHostAndPorts[1] = 10.11.24.38:7001</value> -->
<!-- <value>clusterHostAndPorts[2] = 10.11.24.38:7002</value> -->
<!-- <value>clusterHostAndPorts[3] = 10.11.24.38:7003</value> -->
<!-- <value>clusterHostAndPorts[4] = 10.11.24.38:7004</value> -->
<!-- <value>clusterHostAndPorts[5] = 10.11.24.38:7005</value> -->
<!-- </util:set> -->
<!-- </property> -->
</bean>
<bean id="redisDBUtil" class="com.bbs.redis.util.RedisDBUtil">
</bean>
<bean id="redisCacheUtil" class="com.bbs.redis.util.RedisCacheUtil" scope="singleton">
</bean>
</beans>
6.RedisDBUtil類:
package com.bbs.redis.util;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class RedisDBUtil {
private static final int LOCK_EXPIRE_SECONDS = 300;
private static final int MAX_VALUE_SIZE = 1048576;
private static final int LOG_VALUE_SIZE = 51200;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Resource(
name = "oldRedisTemplate"
)
private RedisTemplate<String, Object> redisTemplate;
public JedisDBUtil() {
}
public static int strToInt(String key) {
if (key != null && !"".equals(key)) {
int num = 0;
for(int i = 0; i < key.length(); ++i) {
num += key.charAt(i);
}
return num;
} else {
return 0;
}
}
public boolean setDB(String key, Object value) {
try {
this.redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception var4) {
return false;
}
}
public boolean setDB(String key, Object value, Integer expireSeconds) {
if (key != null && !"".equals(key.trim())) {
if (value == null) {
return false;
} else {
try {
this.redisTemplate.opsForValue().set(key, value, (long)expireSeconds.intValue(), TimeUnit.SECONDS);
return true;
} catch (Exception var5) {
var5.printStackTrace();
return false;
}
}
} else {
return false;
}
}
public Object getDB(String key) {
return this.redisTemplate.opsForValue().get(key);
}
public Object getDB(String key, boolean readSlave) {
return this.redisTemplate.opsForValue().get(key);
}
public Object getDBNew(final String key, final int expireSeconds, boolean readSlave) {
return key != null && !"".equals(key.trim()) ? this.redisTemplate.execute(new SessionCallback<Object>() {
public Object execute(RedisOperations operations) throws DataAccessException {
operations.expire(key, (long)expireSeconds, TimeUnit.SECONDS);
return operations.opsForValue().get(key);
}
}) : null;
}
public Object getDBNew(String key, int expireSeconds) {
return this.getDBNew(key, expireSeconds, true);
}
public boolean setDBString(String key, String value) {
if (key != null && !"".equals(key.trim())) {
if (value != null && !"".equals(value.trim())) {
try {
this.stringRedisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception var4) {
var4.printStackTrace();
return false;
}
} else {
return false;
}
} else {
return false;
}
}
public String getDBString(String key) {
return this.getDBString(key, true);
}
public String getDBString(String key, boolean readSlave) {
return key != null && !"".equals(key.trim()) ? (String)this.stringRedisTemplate.opsForValue().get(key) : null;
}
public Long getDBKeyExpire(String key, boolean readSlave) {
if (key != null && !"".equals(key.trim())) {
try {
return this.redisTemplate.getExpire(key);
} catch (Exception var4) {
return 0L;
}
} else {
return null;
}
}
public Long getDBKeyExpire(String key) {
return this.getDBKeyExpire(key, true);
}
public boolean deleteDBKey(String key) {
if (key != null && !"".equals(key.trim())) {
try {
this.redisTemplate.delete(key);
return true;
} catch (Exception var3) {
return false;
}
} else {
return false;
}
}
public boolean lock(final String key, final int expireSeconds) {
return key != null && !"".equals(key.trim()) ? ((Boolean)this.redisTemplate.execute(new RedisCallback<Boolean>() {
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
Boolean nx = connection.setNX(key.getBytes(), String.valueOf(System.currentTimeMillis()).getBytes());
if (!nx.booleanValue()) {
try {
Thread.sleep(100L);
} catch (InterruptedException var4) {
var4.printStackTrace();
}
nx = connection.setNX(key.getBytes(), String.valueOf(System.currentTimeMillis()).getBytes());
}
if (nx.booleanValue()) {
connection.expire(key.getBytes(), (long)expireSeconds);
}
return nx;
}
})).booleanValue() : false;
}
public boolean lock(String key) {
return this.lock(key, 300);
}
public boolean unLock(String key) {
if (key != null && !"".equals(key.trim())) {
try {
this.redisTemplate.delete(key);
return true;
} catch (Exception var3) {
var3.printStackTrace();
return false;
}
} else {
return false;
}
}
public Long incr(final String key) {
return key != null && !"".equals(key.trim()) ? (Long)this.redisTemplate.execute(new RedisCallback<Long>() {
public Long doInRedis(RedisConnection connection) throws DataAccessException {
return connection.incr(key.getBytes());
}
}) : null;
}
public Long incrBy(String key, int step) {
return key != null && !"".equals(key.trim()) ? this.redisTemplate.opsForValue().increment(key, (long)step) : null;
}
public boolean batchSetDBString(Map<String, String> map, Integer expireSeconds) {
if (map.isEmpty()) {
return false;
} else if (map.size() > 300) {
return false;
} else {
Iterator var4 = map.entrySet().iterator();
while(var4.hasNext()) {
Entry<String, String> entry = (Entry)var4.next();
this.redisTemplate.opsForValue().set((String)entry.getKey(), entry.getValue(), (long)expireSeconds.intValue(), TimeUnit.SECONDS);
}
return true;
}
}
}
7.RedisCacheUtil類:
package com.bbs.redis.util;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;
@Component
public class RedisCacheUtil {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Resource(
name = "oldRedisTemplate"
)
private RedisTemplate<String, Object> redisTemplate;
private static final String HESSIAN_KEY = "hessian.";
private static final int LOCK_EXPIRE_SECONDS = 300;
private static final int MAX_VALUE_SIZE = 1048576;
private static final int LOG_VALUE_SIZE = 51200;
private static final Log logger = LogFactory.getLog(JedisCacheUtil.class);
public static final int DEFAULT_EXPIRE_SECONDS = 1800;
public JedisCacheUtil() {
}
public boolean setCacheString(String key, String value) {
return this.setCacheString(key, value, Integer.valueOf(1800));
}
public boolean setCacheString(String key, String value, Integer expireSeconds) {
if (key != null && !"".equals(key.trim())) {
if (value != null && !"".equals(value.trim())) {
if (expireSeconds == null) {
return false;
} else {
try {
this.stringRedisTemplate.opsForValue().set(key, value, (long)expireSeconds.intValue(), TimeUnit.SECONDS);
return true;
} catch (Exception var5) {
var5.printStackTrace();
return false;
}
}
} else {
return false;
}
} else {
return false;
}
}
public String getCacheString(String key) {
return key != null && !"".equals(key.trim()) ? (String)this.stringRedisTemplate.opsForValue().get(key) : null;
}
public boolean setCache(String key, Object value) {
return this.setCache(key, value, Integer.valueOf(1800));
}
public boolean setCache(String key, Object value, Integer expireSeconds) {
if (key != null && !"".equals(key.trim())) {
if (expireSeconds == null) {
return false;
} else if (value == null) {
return false;
} else {
try {
this.redisTemplate.opsForValue().set(key, value, (long)expireSeconds.intValue(), TimeUnit.SECONDS);
return true;
} catch (Exception var5) {
return false;
}
}
} else {
return false;
}
}
public Object getCache(String key) {
return key != null && !"".equals(key.trim()) ? this.redisTemplate.opsForValue().get(key) : null;
}
public Long incr(final String key) {
return key != null && !"".equals(key.trim()) ? (Long)this.redisTemplate.execute(new RedisCallback<Long>() {
public Long doInRedis(RedisConnection connection) throws DataAccessException {
return connection.incr(key.getBytes());
}
}) : null;
}
public Long incrBy(String key, int step) {
return key != null && !"".equals(key.trim()) ? this.redisTemplate.opsForValue().increment(key, (long)step) : null;
}
public Long decr(final String key) {
return key != null && !"".equals(key.trim()) ? (Long)this.redisTemplate.execute(new RedisCallback<Long>() {
public Long doInRedis(RedisConnection connection) throws DataAccessException {
return connection.decr(key.getBytes());
}
}) : null;
}
public Long decrBy(final String key, final int step) {
return key != null && !"".equals(key.trim()) ? (Long)this.redisTemplate.execute(new RedisCallback<Long>() {
public Long doInRedis(RedisConnection connection) throws DataAccessException {
return connection.decrBy(key.getBytes(), (long)step);
}
}) : null;
}
/** @deprecated */
@Deprecated
public Long deleteKey(final String key) {
return key != null && !"".equals(key.trim()) ? (Long)this.redisTemplate.execute(new RedisCallback<Long>() {
public Long doInRedis(RedisConnection connection) {
connection.del(new byte[][]{key.getBytes()});
return null;
}
}, true) : 0L;
}
public Long deleteCacheStringKey(String key) {
return this.deleteKey(key);
}
/** @deprecated */
@Deprecated
public Long deleteStrToBytesKey(String key) {
return this.deleteKey(key);
}
public Long deleteCacheKey(String key) {
return this.deleteStrToBytesKey(key);
}
public Long getKeyExpire(String key) {
if (key != null && !"".equals(key.trim())) {
try {
return this.redisTemplate.getExpire(key);
} catch (Exception var3) {
return 0L;
}
} else {
return 0L;
}
}
public Long setKeyExpire(String key, int expireSeconds) {
if (key != null && !"".equals(key.trim())) {
Boolean t = this.redisTemplate.expire(key, (long)expireSeconds, TimeUnit.SECONDS);
return t.booleanValue() ? 1L : 0L;
} else {
return null;
}
}
public boolean keyExists(final String key) {
return key != null && !"".equals(key.trim()) ? ((Boolean)this.redisTemplate.execute(new RedisCallback<Boolean>() {
public Boolean doInRedis(RedisConnection connection) {
return connection.exists(key.getBytes());
}
})).booleanValue() : false;
}
public boolean lock(final String key, final int expireSeconds) {
return key != null && !"".equals(key.trim()) ? ((Boolean)this.redisTemplate.execute(new RedisCallback<Boolean>() {
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
Boolean nx = connection.setNX(key.getBytes(), String.valueOf(System.currentTimeMillis()).getBytes());
if (!nx.booleanValue()) {
try {
Thread.sleep(100L);
} catch (InterruptedException var4) {
var4.printStackTrace();
}
nx = connection.setNX(key.getBytes(), String.valueOf(System.currentTimeMillis()).getBytes());
}
if (nx.booleanValue()) {
connection.expire(key.getBytes(), (long)expireSeconds);
}
return nx;
}
})).booleanValue() : false;
}
public boolean lock(String key) {
return this.lock(key, 300);
}
public boolean unLock(String key) {
if (key != null && !"".equals(key.trim())) {
try {
this.redisTemplate.delete(key);
return true;
} catch (Exception var3) {
var3.printStackTrace();
return false;
}
} else {
return false;
}
}
public boolean watchMethodCall(String ip, long maxNum, int expireSeconds) {
return this.incrWatchKeyNew(ip, expireSeconds, maxNum);
}
private boolean incrWatchKey(final String key, final int expireSeconds, final long maxNum) {
Long res = (Long)this.redisTemplate.execute(new RedisCallback<Long>() {
public Long doInRedis(RedisConnection connection) throws DataAccessException {
long count = 0L;
RedisSerializer<String> rs = JedisCacheUtil.this.redisTemplate.getKeySerializer();
Long ttl = connection.ttl(key.getBytes());
if (ttl.longValue() > 0L && ttl.longValue() <= (long)expireSeconds) {
String str = (String)JedisCacheUtil.this.redisTemplate.getValueSerializer().deserialize(connection.get(key.getBytes()));
if (str != null && Long.valueOf(str).longValue() < maxNum) {
count = connection.incr(rs.serialize(key)).longValue();
}
} else {
connection.set(rs.serialize(key), rs.serialize("0"));
connection.expire(rs.serialize(key), (long)expireSeconds);
count = connection.incr(rs.serialize(key)).longValue();
}
return count;
}
});
return res.longValue() != 0L && res.longValue() <= maxNum;
}
private boolean incrWatchKeyNew(String key, int expireSeconds, long maxNum) {
return maxNum > 50000L ? false : this.incrWatchKey(key, expireSeconds, maxNum);
}
}
8.SpringEl表達式工具類:
package com.bbs.aspects;
import com.bbs.common.util.ArrayUtil;
import com.bbs.common.util.DateUtil;
import com.bbs.common.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class SpringElUtil {
private final static Logger logger = LoggerFactory.getLogger(RedisCacheUtil.class);
/** Key組成成員分隔符 */
private final static String KEY_MEMBER_SPLIT = "_";
/** Key列表分隔符 */
private final static String KEY_SPLIT = ",";
/** springEl關鍵字 */
private final static String SPRING_EL_KEY_WORD = "#";
/**
* 獲取方法參數名稱
* @param method
* @return
*/
public static String[] getParamterNames(Method method){
LocalVariableTableParameterNameDiscoverer u =
new LocalVariableTableParameterNameDiscoverer();
return u.getParameterNames(method);
}
/**
* 獲取redis 鍵
* @param args 目標方法參數
* @param targetMethod 目標方法
* @param keyPrefix 緩存key前綴
* @param keyMembers 緩存key成員
* @param keyDateFormat 緩存key成員日期的格式
* @return
*/
public static String getCacheKey(Object[] args,Method targetMethod,String keyPrefix,String [] keyMembers,String keyDateFormat){
//創建SpringEL表達式轉換器
ExpressionParser parser = new SpelExpressionParser();
//Spring
EvaluationContext context = new StandardEvaluationContext();
//獲取目標方法參數名
String [] paramNames = RedisCacheUtil.getParamterNames(targetMethod);
for(int i=0;i<args.length;i++){
context.setVariable(paramNames[i],args[i]);
}
//組裝Key
StringBuilder cacheKeySb = new StringBuilder(keyPrefix);
for(String keyMember : keyMembers) {
cacheKeySb.append(KEY_MEMBER_SPLIT);
cacheKeySb.append(getValue(parser,context,keyMember,keyDateFormat));
}
return cacheKeySb.toString();
}
/**
* 獲取redis 鍵
* @param args 目標方法參數
* @param targetMethod 目標方法
* @param keys 緩存key
* @param keyDateFormat 緩存key成員日期的格式
* @return
*/
public static List<String> getCacheKeys(Object[] args, Method targetMethod,String [] keys, String keyDateFormat){
//創建SpringEL表達式轉換器
ExpressionParser parser = new SpelExpressionParser();
//Spring
EvaluationContext context = new StandardEvaluationContext();
//獲取目標方法參數名
String [] paramNames = RedisCacheUtil.getParamterNames(targetMethod);
for(int i=0;i<args.length;i++){
context.setVariable(paramNames[i],args[i]);
}
//key列表爲空,返回空
if(ArrayUtil.isEmpty(keys)){
return null;
}
List<String> keyList = new ArrayList<String>();
//循環遍歷key
for(String key : keys) {
try {
String[] keyMembers = StringUtil.split(key, KEY_SPLIT);
if (ArrayUtil.isEmpty(keyMembers)) {
continue;
}
//組裝key
StringBuilder cacheKeySb = new StringBuilder();
for (String keyMember : keyMembers) {
Object value = getValue(parser,context,keyMember,keyDateFormat);
if(null == value){
cacheKeySb = null;
break;
}
cacheKeySb.append(getValue(parser,context,keyMember,keyDateFormat));
cacheKeySb.append(KEY_MEMBER_SPLIT);
}
//如果cacheKeySb非空 && 大小>0
if(null != cacheKeySb && cacheKeySb.length()>0) {
//刪除key
cacheKeySb.deleteCharAt(cacheKeySb.lastIndexOf(KEY_MEMBER_SPLIT));
keyList.add(cacheKeySb.toString());
}
} catch(Throwable e) {
logger.error("RedisCacheUtil.getCacheKeys("+key+"):"+e.getMessage(),e);
}
}
return keyList;
}
/**
* 獲取值
* @param parser
* @param context
* @param keyMember
* @param keyDateFormat
* @return
*/
private static Object getValue(ExpressionParser parser,EvaluationContext context,String keyMember,String keyDateFormat){
if (keyMember.startsWith(SPRING_EL_KEY_WORD)) {
Expression expression = parser.parseExpression(keyMember);
Object value = expression.getValue(context);
if(null == value){
return null;
}
//如果值類型爲java.util.Date,則進行格式轉換
if (value instanceof java.util.Date && StringUtil.isNotBlank(keyDateFormat)) {
return DateUtil.format((java.util.Date) value, keyDateFormat);
} else {
return value;
}
}else{
return keyMember;
}
}
}
【應用場景一:springEl表達式註解緩存實踐與使用】
1.RedisCache註解類:
package com.bbs.aspects;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface RedisCache {
/** 表示緩存key的前綴 */
String keyPrefix();
/**
表示緩存Key成員,可以由關鍵字或springEl表達式組成(每個成員由下劃線(_)拼接而成):
#表示springEl表達式,非#表示關鍵字不會進行springEl解析。
*/
String [] keyMember();
/** 表示緩存中日期成員會被keyDateFormat格式轉換成字符串 */
String keyDateFormat() default "";
/** 過時時間(單位秒) */
int expireSecond() default 0;
}
2.RedisCacheAspect切面類:
package com.bbs.aspects;
import com.bbs.SpringElUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Service;
import java.lang.reflect.Method;
@Service
@Aspect
public class RedisCacheAspect {
@Autowired
private RedisCacheUtil redisCacheUtil;
private Logger logger = LoggerFactory.getLogger(RedisCacheAspect.class);
@Pointcut(value="execution(* com.bbs.service.impl..*.*(..)) && @annotation(com.bbs.aspects.RedisCache)")
public void cachePoint() {
}
@Around(value="cachePoint()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
Method targetMethod = methodSignature.getMethod();
//緩存緩存枚舉
RedisCache redisCache = targetMethod.getAnnotation(RedisCache.class);
String cachedKey = null;
//從緩存中獲取數據
try {
cachedKey = getCacheKey(joinPoint);
//如果cacheKey非空,從緩存中獲取
if(StringUtil.isNotBlank(cachedKey)) {
Object object = redisCacheUtil.getCache(cachedKey);
if (null != object) {
logger.info("data from cachedKey:"+cachedKey);
return object;
}
}
} catch(Throwable e) {
logger.error("RedisCacheAspect.around.getCache:"+e.getMessage(),e);
}
// 以改變後的參數去執行目標方法,並保存目標方法執行後的返回值
Object retVal = joinPoint.proceed(joinPoint.getArgs());
try {
//如果cacheKey空或retV爲空,不添加到緩存
if(StringUtil.isBlank(cachedKey) || null == retVal) {
return retVal;
}
//如果集合爲空,不緩存
if(retVal instanceof java.util.Collection && CollectionUtil.isEmpty((java.util.Collection)retVal)){
return retVal;
}
redisCacheUtil.setCache(cachedKey, retVal,redisCache.expireSecond());
logger.info("data into cachedKey:"+cachedKey);
} catch (Throwable e) {
logger.error("RedisCacheAspect.around.setCache:"+e.getMessage(),e);
}
return retVal;
}
/**
* 獲取CacheKey
* @param joinPoint
* @return
*/
private String getCacheKey(ProceedingJoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
Method targetMethod = methodSignature.getMethod();
//緩存緩存枚舉
RedisCache redisCache = targetMethod.getAnnotation(RedisCache.class);
String keyPrefix = redisCache.keyPrefix();
String [] keyMember = redisCache.keyMember();
String keyDateFormat = redisCache.keyDateFormat();
return SpringElUtil.getCacheKey(args,targetMethod,keyPrefix,keyMember,keyDateFormat);
}
/**
* 獲取方法參數名稱
* @param method
* @return
*/
private String[] getParamterNames(Method method){
LocalVariableTableParameterNameDiscoverer u =
new LocalVariableTableParameterNameDiscoverer();
return u.getParameterNames(method);
}
}
3.RedisCache緩存註解使用方法:
@RedisCache(keyPrefix={"CacheUserIdType"},keyMember = {"#orderDO.userId","#orderDO.type"})
public OrderStatus saveOrder(OrderDO orderDO){
...
}
使用說明:
條件:
1)#orderDO.userId 值爲1
2)##orderDO.type 值爲preSale
結論:
查詢結果(結果爲null或空集合不會被緩存)會被緩存到對應Key中:
key1:CacheUserIdType_1_preSale
【應用場景二:springEl表達式註解緩存刪除實踐與使用】
1.RedisCacheDelete註解類:
package com.bbs.aspects;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface RedisCacheDelete {
/** 表示緩存key的前綴 */
String keyPrefix();
/**
表示緩存Key成員,可以由關鍵字或springEl表達式組成(每個成員由下劃線(_)拼接而成):
#表示springEl表達式,非#表示關鍵字不會進行springEl解析
*/
String [] keyMember();
/** cachedKey:日期格式 */
String keyDateFormat() default "";
}
2.RedisCacheDeleteAspect切面類:
package com.bbs.aspects;
import com.bbs.redis.util.RedisCacheUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.lang.reflect.Method;
@Service
@Aspect
public class RedisCacheDeleteAspect {
private Logger logger = LoggerFactory.getLogger(RedisCacheDeleteAspect.class);
@Autowired
private RedisCacheUtil redisCacheUtil;
@Pointcut(value="execution(* com.bbs.service.impl..*.*(..)) && @annotation(com.bbs.aspects.RedisCacheDelete)")
public void cacheDeletePoint() {
}
@After(value="cacheDeletePoint()")
public void cacheDelete(JoinPoint joinPoint) throws Throwable {
//從緩存中獲取數據
try {
String cachedKey = getCacheKey(joinPoint);
//如果cacheKey非空,從緩存中獲取
if(StringUtil.isNotBlank(cachedKey)) {
redisCacheUtil.deleteCacheKey(cachedKey);
logger.info("cacheDelete.deleteCacheKey.cachedKey:"+cachedKey);
}
} catch(Throwable e) {
logger.error("RedisCacheAspect.CacheDelete.deleteCacheKey:"+e.getMessage(),e);
}
}
/**
* 獲取CacheKey
* @param joinPoint
* @return
*/
private String getCacheKey(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
Method targetMethod = methodSignature.getMethod();
//緩存緩存枚舉
RedisCacheDelete redisCache = targetMethod.getAnnotation(RedisCacheDelete.class);
String keyPrefix = redisCache.keyPrefix();
String [] keyMember = redisCache.keyMember();
String keyDateFormat = redisCache.keyDateFormat();
return SpringElUtil.getCacheKey(args,targetMethod,keyPrefix,keyMember,keyDateFormat);
}
}
3.RedisCacheDelete緩存註解使用方法:
@RedisCacheDelete(keyPrefix={"CacheUserIdType"},keyMember = {"#orderDO.userId","#orderDO.type"})
public OrderStatus deleteOrder(OrderDO orderDO){
...
}
使用說明:
條件:
1)#orderDO.userId 值爲1
2)#orderDO.type 值爲preSale
結論:
對應Key的緩存會被刪除:
key1:CacheUserIdType_1_preSale
【應用場景三:springEl表達式註解緩存批量刪除實踐與使用】
1.RedisCachesRemove註解類:
package com.bbs.aspects;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface RedisCachesRemove {
/**
keys表示多個cacheKey,其中cacheKey可以由關鍵字或springEl表達式成員組成,成員之間用逗號進行分割.
解析後生成的key由下劃線(_)拼接而成:
#表示springEl表達式,非#表示關鍵字不會進行springEl解析
*/
String [] keys();
/** cachedKey:日期格式 */
String keyDateFormat() default "";
}
2.RedisCachesRemoveAspect切面類:
package com.bbs.aspects;
import com.bbs.redis.util.RedisCacheUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.lang.reflect.Method;
import java.util.List;
@Service
@Aspect
public class RedisCachesRemoveAspect {
private Logger logger = LoggerFactory.getLogger(RedisCachesRemoveAspect.class);
@Autowired
private RedisCacheUtil redisCacheUtil;
@Pointcut(value="execution(* com.bbs.service.impl..*.*(..)) && @annotation(com.bbs.aspects.RedisCachesRemove)")
public void cachesRemovePoint() {
}
@After(value="cachesRemovePoint()")
public void cachesRemove(JoinPoint joinPoint) throws Throwable {
//從緩存中獲取數據
try {
List<String> cachedKeyList = getCacheKeys(joinPoint);
for(String cacheKey : cachedKeyList) {
try {
//如果cacheKey非空,從緩存中獲取
if (StringUtil.isNotBlank(cacheKey)) {
redisCacheUtil.deleteCacheKey(cacheKey);
logger.info("cachesRemove.deleteCacheKey.cachedKey:"+cacheKey);
}
}catch (Exception ex){
logger.error("RedisCachesRemoveAspect.cachesRemove.deleteCacheKey:"+ex.getMessage(),ex);
}
}
} catch(Throwable e) {
logger.error("RedisCachesRemoveAspect.cachesRemove.getCacheKeys:"+e.getMessage(),e);
}
}
/**
* 獲取CacheKey
* @param joinPoint
* @return
*/
private List<String> getCacheKeys(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
Method targetMethod = methodSignature.getMethod();
//緩存緩存枚舉
RedisCachesRemove redisCache = targetMethod.getAnnotation(RedisCachesRemove.class);
String [] keys = redisCache.keys();
String keyDateFormat = redisCache.keyDateFormat();
return SpringElUtil.getCacheKeys(args,targetMethod,keys,keyDateFormat);
}
}
3.RedisCachesRemove緩存註解使用方法:
@RedisCachesRemove(keys = {"CacheUserId,#orderDO.userId","CacheModuleType,#orderDO.type"})
public OrderStatus deleteOrder(OrderDO orderDO){
...
}
使用說明:
條件:
1)#orderDO.userId 值爲1
2)#orderDO.type 值爲preSale
結論:
對應如下兩個Key的緩存會被刪除:
key1:CacheUserId_1
key2:CacheType_preSale
注意:
目前已測支持springEl表達式:
參數爲基本數據類型或對應類類型:#參數名
參數爲類類型,參數對象的屬性值:#參數名.屬性名
參數爲數組,參數對象位置值:#參數名[0]
參考:
https://blog.csdn.net/BinshaoNo_1/article/details/84579326