Redis缓存实践:自定义注解、基于Spring注解

一、自定义注解开发Redis

1、java注解

参考:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html

2、Redis-Spring配置

配置它两个如果顺利你不会抱任何错,不顺利的话错误停不下来。

1、Redis是集群还是单机,都没有问题,参见本博客的Redis集群搭建方式。

2、最主要的问题会发生在包冲突上,mvn dependece tree 命令可以解决,但是也可以简单点打开在IDE中打开看看依赖的一般是Spring的版本会冲突。尤其是引入:spring-data-redis包。

需要的基本配置:

            <dependency>
				<groupId>org.springframework.data</groupId>
				<artifactId>spring-data-redis</artifactId>
				<version>1.6.0.RELEASE</version>
			</dependency>
            <dependency>
				<groupId>org.springframework.data</groupId>
				<artifactId>spring-data-commons</artifactId>
				<version>1.12.2.RELEASE</version>
			</dependency>
            <dependency>
				<groupId>redis.clients</groupId>
				<artifactId>jedis</artifactId>
				<version>2.7.3</version>
			</dependency>

spring-data-common也可以不添加。

3、自定义注解开发

开发步骤:

1、创建注解

2、位注解添加切面

3、配置包扫描

参考:http://blog.youkuaiyun.com/cai_chinasoft/article/details/51680148

这篇博客适合入门学习,但是问题还是有的,在保存和删除缓存中使用了哈希数据结构,默认过期时间是永久,即:没有删除操作一直存在。哈希在删除上删除的数据很多粒度有些大。

	<aop:aspectj-autoproxy />
	<context:component-scan base-package="com.你的切面所在的包" />
	<context:annotation-config />

测试可以使用redis客户端查看数据。

 

二、RedisUtils开发

1、spring-redis配置文件,其实同上。但是要贴出了


	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="testWhileIdle" value="true" />
		<property name="minEvictableIdleTimeMillis" value="60000" />
		<property name="timeBetweenEvictionRunsMillis" value="30000" />
		<property name="numTestsPerEvictionRun" value="-1" />
		<property name="maxTotal" value="50" />
		<property name="maxIdle" value="50" />
		<property name="minIdle" value="10" />
	</bean>

	<bean id="jedisSentinelPool" class="redis.clients.jedis.JedisSentinelPool" destroy-method="destroy">
		<constructor-arg name="masterName">
			<value>master1</value>
		</constructor-arg>
		<constructor-arg name="sentinels">
			<set value-type="java.lang.String">
				<value>${redis.host}</value>
			</set>
		</constructor-arg>
		<constructor-arg name="poolConfig" ref="jedisPoolConfig" />
	</bean>

2、工具类 

​
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;

/**
 * 
 * 
 */
public class RedisUtils {

	private static Logger logger = Logger.getLogger(RedisUtils.class);

	/** 默认缓存时间 */
	private static final int DEFAULT_CACHE_SECONDS = 60 * 60 * 1;// 单位秒 设置成一个钟

	/** 连接池 **/
	private static JedisSentinelPool jedisSentinelPool;

	/**
	 * 释放redis资源
	 * 
	 * @param jedis
	 */
	private static void releaseResource(Jedis jedis) {
		if (jedis != null) {
			jedisSentinelPool.returnResource(jedis);
		}
	}

	/**
	 * 删除Redis中的所有key
	 * 
	 * @param jedis
	 * @throws Exception
	 */
	public static void flushAll() {
		Jedis jedis = null;
		try {
			jedis = jedisSentinelPool.getResource();
			jedis.flushAll();
		} catch (Exception e) {
			logger.error("Cache清空失败:" + e);
		} finally {
			releaseResource(jedis);
		}
	}

	/**
	 * 保存一个对象到Redis中(缓存过期时间:使用此工具类中的默认时间) . <br/>
	 * 
	 * @param key
	 *            键 . <br/>
	 * @param object
	 *            缓存对象 . <br/>
	 * @return true or false . <br/>
	 * @throws Exception
	 */
	public static Boolean save(Object key, Object object) {
		return save(key, object, DEFAULT_CACHE_SECONDS);
	}

	/**
	 * 保存一个对象到redis中并指定过期时间
	 * 
	 * @param key
	 *            键 . <br/>
	 * @param object
	 *            缓存对象 . <br/>
	 * @param seconds
	 *            过期时间(单位为秒).<br/>
	 * @return true or false .
	 */
	public static Boolean save(Object key, Object object, int seconds) {
		Jedis jedis = null;
		try {
			jedis = jedisSentinelPool.getResource();
			jedis.set(SerializeUtils.serialize(key), SerializeUtils.serialize(object));
			jedis.expire(SerializeUtils.serialize(key), seconds);
			return true;
		} catch (Exception e) {
			logger.error("Cache保存失败:" + e);
			return false;
		} finally {
			releaseResource(jedis);
		}
	}

	/**
	 * 根据缓存键获取Redis缓存中的值.<br/>
	 * 
	 * @param key
	 *            键.<br/>
	 * @return Object .<br/>
	 * @throws Exception
	 */
	public static Object get(Object key) {
		Jedis jedis = null;
		try {
			jedis = jedisSentinelPool.getResource();
			byte[] obj = jedis.get(SerializeUtils.serialize(key));
			return obj == null ? null : SerializeUtils.unSerialize(obj);
		} catch (Exception e) {
			logger.error("Cache获取失败:" + e);
			return null;
		} finally {
			releaseResource(jedis);
		}
	}

	/**
	 * 根据缓存键清除Redis缓存中的值.<br/>
	 * 
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static Boolean del(Object key) {
		Jedis jedis = null;
		try {
			// System.out.println(key);
			jedis = jedisSentinelPool.getResource();
			jedis.del(SerializeUtils.serialize(key));
			return true;
		} catch (Exception e) {
			logger.error("Cache删除失败:" + e);
			return false;
		} finally {
			releaseResource(jedis);
		}
	}

	/**
	 * 根据缓存键清除Redis缓存中的值.<br/>
	 * 
	 * @param keys
	 * @return
	 * @throws Exception
	 */
	public static Boolean del(Object... keys) {
		Jedis jedis = null;
		try {
			jedis = jedisSentinelPool.getResource();
			jedis.del(SerializeUtils.serialize(keys));
			return true;
		} catch (Exception e) {
			logger.error("Cache删除失败:" + e);
			return false;
		} finally {
			releaseResource(jedis);
		}
	}

	/**
	 * 
	 * @param key
	 * @param seconds
	 *            超时时间(单位为秒)
	 * @return
	 */
	public static Boolean expire(Object key, int seconds) {

		Jedis jedis = null;
		try {
			jedis = jedisSentinelPool.getResource();
			jedis.expire(SerializeUtils.serialize(key), seconds);
			return true;
		} catch (Exception e) {
			logger.error("Cache设置超时时间失败:" + e);
			return false;
		} finally {
			releaseResource(jedis);
		}
	}

	/**
	 * 添加一个内容到指定key的hash中
	 * 
	 * @param key
	 * @param field
	 * @param value
	 * @return
	 */
	public static Boolean addHash(String key, Object field, Object value) {
		Jedis jedis = null;
		try {
			jedis = jedisSentinelPool.getResource();
			jedis.hset(SerializeUtils.serialize(key), SerializeUtils.serialize(field), SerializeUtils.serialize(value));
			return true;
		} catch (Exception e) {
			logger.error("Cache保存失败:" + e);
			return false;
		} finally {
			releaseResource(jedis);
		}
	}

	/**
	 * 从指定hash中拿一个对象
	 * 
	 * @param key
	 * @param field
	 * @return
	 */
	public static Object getHash(Object key, Object field) {
		Jedis jedis = null;
		try {
			jedis = jedisSentinelPool.getResource();
			byte[] obj = jedis.hget(SerializeUtils.serialize(key), SerializeUtils.serialize(field));
			return SerializeUtils.unSerialize(obj);
		} catch (Exception e) {
			logger.error("Cache读取失败:" + e);
			return null;
		} finally {
			releaseResource(jedis);
		}
	}

	/**
	 * 从hash中删除指定filed的值
	 * 
	 * @param key
	 * @param field
	 * @return
	 */
	public static Boolean delHash(Object key, Object field) {
		Jedis jedis = null;
		try {
			jedis = jedisSentinelPool.getResource();
			long result = jedis.hdel(SerializeUtils.serialize(key), SerializeUtils.serialize(field));
			return result == 1 ? true : false;
		} catch (Exception e) {
			logger.error("Cache删除失败:" + e);
			return null;
		} finally {
			releaseResource(jedis);
		}
	}

	/**
	 * 拿到缓存中所有符合pattern的key
	 * 
	 * @param pattern
	 * @return
	 */
	public static Set<byte[]> keys(String pattern) {
		Jedis jedis = null;
		try {
			jedis = jedisSentinelPool.getResource();
			Set<byte[]> allKey = jedis.keys(("*" + pattern + "*").getBytes());
			return allKey;
		} catch (Exception e) {
			logger.error("Cache获取失败:" + e);
			return new HashSet<byte[]>();
		} finally {
			releaseResource(jedis);
		}
	}

	/**
	 * 获得hash中的所有key value
	 * 
	 * @param key
	 * @return
	 */
	public static Map<byte[], byte[]> getAllHash(Object key) {
		Jedis jedis = null;
		try {
			jedis = jedisSentinelPool.getResource();
			Map<byte[], byte[]> map = jedis.hgetAll(SerializeUtils.serialize(key));
			return map;
		} catch (Exception e) {
			logger.error("Cache获取失败:" + e);
			return null;
		} finally {
			releaseResource(jedis);
		}
	}

	/**
	 * 判断一个key是否存在
	 * 
	 * @param key
	 * @return
	 */
	public static Boolean exists(Object key) {
		Jedis jedis = null;
		Boolean result = false;
		try {
			jedis = jedisSentinelPool.getResource();
			result = jedis.exists(SerializeUtils.serialize(key));
			return result;
		} catch (Exception e) {
			logger.error("Cache获取失败:" + e);
			return false;
		} finally {
			releaseResource(jedis);
		}
	}

	public void setJedisSentinelPool(JedisSentinelPool jedisSentinelPool) {
		RedisUtils.jedisSentinelPool = jedisSentinelPool;
	}

	public static JedisSentinelPool getJedisSentinelPool() {
		return jedisSentinelPool;
	}
	
	

}
​

3、实现cache接口

package com.lienbo.redis.rediscacheImpl;

import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.stereotype.Component;

import wusc.edu.pay.common.utils.cache.redis.RedisUtils;


/**
 * 
 * 实现spring的缓存接口
 */

@Component("redisCache")
public class RedisCache implements Cache {
	/**缓存的命名属性**/
	private String name;

	public RedisUtils cache = new RedisUtils();
	
	/**
	 * 清空所有的缓存 
	 */
	public void clear() {
		cache.flushAll();
	}

	@Override
	public void evict(Object key) {
		cache.del(key);
	}

	/**
	 * 根据Key值获得缓存数据
	 */
	public ValueWrapper get(Object key) {
		ValueWrapper result = null;
		Object thevalue = cache.get(key);
		if (thevalue != null) {
			result = new SimpleValueWrapper(thevalue);
		}
		return result;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public Object getNativeCache() {
		return cache;
	}
	
	/**添加缓存*/
	public void put(Object arg0, Object arg1) {
		cache.save(arg0, arg1,20000);
	}

	public RedisCache() {
	}

	public RedisCache(String name) {
		this.name = name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

这里有对spring cache的详细说明

https://www.ibm.com/developerworks/cn/opensource/os-cn-spring-cache//

4、缓存管理:

package com.lienbo.redis.rediscacheImpl;

import java.util.Collection;

import org.springframework.cache.Cache;
import org.springframework.cache.support.AbstractCacheManager;

/**
 * 继承了 spring 内置的 AbstractCacheManager 
 * 管理 RedisCache 类缓存管理
 */
public class CacheManager<T extends Object> extends AbstractCacheManager {

	private Collection<? extends RedisCache> caches;

	public void setCaches(Collection<? extends RedisCache> caches) {
		this.caches = caches;
	}

	@Override
	protected Collection<? extends Cache> loadCaches() {
		return this.caches;
	}
}

5、配置文件

	<bean id="redisUtils" class="om.lienbo.RedisUtils">
		<property name="jedisSentinelPool" ref="jedisSentinelPool" />
	</bean>
	<!-- redis caceh config end -->

	 <!-- generic cache manager --> 
   <cache:annotation-driven />
   <!-- generic cache manager --> 
   <bean id="cacheManager" class="com.lienbo.CacheManager">
     <property name="caches"> 
       <set> 
         <bean 
           class="om.lienbo.RedisCache"
           p:name="redisCache" /> 
       </set> 
     </property> 
   </bean> 

 

三、使用sprign cache实现redis缓存

其实原理同上:

1、配置文件

    <cache:annotation-driven />  
  
    <!-- 缓存管理器 -->  
    <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">  
        <property name="caches">  
            <set>  
                <bean class="com.config.SystemRedisCache">  
                    <property name="redisTemplate" ref="redisTemplate" />  
                    <property name="name" value="default" />  
                    <property name="timeout" value="${redis.timeout}" />  
                </bean>  

                <bean class="com.config.SystemRedisCache">  
                    <property name="redisTemplate" ref="redisTemplate" />  
<!--valeue 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 我是用来类名点方法名的方式 redisTemplate也可以配置多个-->
                    <property name="name" value="userService.queryUserById" />  
                    <property name="timeout" value="${redis.timeout}" />  
                </bean>  

            </set>  
        </property>  
    </bean>  

 2、实现接口

这里有个坑:

注意注入的时候

三个redisTemplate name timeout 属性中 getName是实现接口的方法不要返回null,否则会报错的!

import org.springframework.cache.Cache;  
import org.springframework.cache.support.SimpleValueWrapper;  
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.util.StringUtils;  
  

public class SystemRedisCache implements Cache {  
  
    /** 
     * Redis 
     */  
    private RedisTemplate<String, Object> redisTemplate;  
  
    /** 
     * 缓存名称 
     */  
    private String name;  
  
    /** 
     * 超时时间 
     */  
    private long timeout;  
  
    /* 
     * (non-Javadoc) 
     * @see org.springframework.cache.Cache#getName() 
     */  
    @Override  
    public String getName() {  
        return this.name;  
    }  
  
    /* 
     * (non-Javadoc) 
     * @see org.springframework.cache.Cache#getNativeCache() 
     */  
    @Override  
    public Object getNativeCache() {  
        // TODO Auto-generated method stub  
        return this.redisTemplate;  
    }  
  
    /* 
     * (non-Javadoc) 
     * @see org.springframework.cache.Cache#get(java.lang.Object) 
     */  
    @Override  
    public ValueWrapper get(Object key) {  
        if (StringUtils.isEmpty(key)) {  
            return null;  
        } else {  
            final String finalKey;  
            if (key instanceof String) {  
                finalKey = (String) key;  
            } else {  
                finalKey = key.toString();  
            }  
            Object object = null;  
            object = redisTemplate.execute(new RedisCallback<Object>() {  
                public Object doInRedis(RedisConnection connection) throws DataAccessException {  
                    byte[] key = finalKey.getBytes();  
                    byte[] value = connection.get(key);  
                    if (value == null) {  
                        return null;  
                    }  
                    return SerializableObjectUtil.unserialize(value);  
                }  
            });  
            return (object != null ? new SimpleValueWrapper(object) : null);  
        }  
    }  
  
    /* 
     * (non-Javadoc) 
     * @see org.springframework.cache.Cache#get(java.lang.Object, java.lang.Class) 
     */  
    @SuppressWarnings("unchecked")  
    @Override  
    public <T> T get(Object key, Class<T> type) {  
        if (StringUtils.isEmpty(key) || null == type) {  
            return null;  
        } else {  
            final String finalKey;  
            final Class<T> finalType = type;  
            if (key instanceof String) {  
                finalKey = (String) key;  
            } else {  
                finalKey = key.toString();  
            }  
            final Object object = redisTemplate.execute(new RedisCallback<Object>() {  
                public Object doInRedis(RedisConnection connection) throws DataAccessException {  
                    byte[] key = finalKey.getBytes();  
                    byte[] value = connection.get(key);  
                    if (value == null) {  
                        return null;  
                    }  
                    return SerializableObjectUtil.unserialize(value);  
                }  
            });  
            if (finalType != null && finalType.isInstance(object) && null != object) {  
                return (T) object;  
            } else {  
                return null;  
            }  
        }  
    }  
  
    /* 
     * (non-Javadoc) 
     * @see org.springframework.cache.Cache#put(java.lang.Object, java.lang.Object) 
     */  
    @Override  
    public void put(final Object key, final Object value) {  
        if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {  
            return;  
        } else {  
            final String finalKey;  
            if (key instanceof String) {  
                finalKey = (String) key;  
            } else {  
                finalKey = key.toString();  
            }  
            if (!StringUtils.isEmpty(finalKey)) {  
                final Object finalValue = value;  
                redisTemplate.execute(new RedisCallback<Boolean>() {  
                    @Override  
                    public Boolean doInRedis(RedisConnection connection) {  
                        connection.set(finalKey.getBytes(), SerializableObjectUtil.serialize(finalValue));  
                        // 设置超时间  
                        connection.expire(finalKey.getBytes(), timeout);  
                        return true;  
                    }  
                });  
            }  
        }  
    }  
  
    /* 
     * 根据Key 删除缓存 
     */  
    @Override  
    public void evict(Object key) {  
        if (null != key) {  
            final String finalKey;  
            if (key instanceof String) {  
                finalKey = (String) key;  
            } else {  
                finalKey = key.toString();  
            }  
            if (!StringUtils.isEmpty(finalKey)) {  
                redisTemplate.execute(new RedisCallback<Long>() {  
                    public Long doInRedis(RedisConnection connection) throws DataAccessException {  
                        return connection.del(finalKey.getBytes());  
                    }  
                });  
            }  
        }  
    }  
  
    /* 
     * 清楚系统缓存 
     */  
    @Override  
    public void clear() {  
    }  
  
    public RedisTemplate<String, Object> getRedisTemplate() {  
        return redisTemplate;  
    }  
  
    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {  
        this.redisTemplate = redisTemplate;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public long getTimeout() {  
        return timeout;  
    }  
  
    public void setTimeout(long timeout) {  
        this.timeout = timeout;  
    }  
}  

3、使用方式

 @Cacheable(
 value = "userService.queryUserById", 
 key = "new String('commonService.queryUserById')+#id",
 condition = "null != #id and #id.length() > 0")  

 public List<User> queryUserById(String id) { 
    return null;
 }

4、附录 

@Cacheable、@CachePut、@CacheEvict 注释介绍

通过上面的例子,我们可以看到 spring cache 主要使用两个注释标签,即 @Cacheable、@CachePut 和 @CacheEvict,我们总结一下其作用和配置方法。

表 1. @Cacheable 作用和配置方法

@Cacheable 的作用主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
@Cacheable 主要的参数
value缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:
@Cacheable(value=”mycache”) 或者 
@Cacheable(value={”cache1”,”cache2”}
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合例如:
@Cacheable(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存例如:
@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

表 2. @CachePut 作用和配置方法

@CachePut 的作用主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用
@CachePut 主要的参数
value缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:
@Cacheable(value=”mycache”) 或者 
@Cacheable(value={”cache1”,”cache2”}
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合例如:
@Cacheable(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存例如:
@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

表 3. @CacheEvict 作用和配置方法

@CachEvict 的作用主要针对方法配置,能够根据一定的条件对缓存进行清空
@CacheEvict 主要的参数
value缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:
@CachEvict(value=”mycache”) 或者 
@CachEvict(value={”cache1”,”cache2”}
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合例如:
@CachEvict(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才清空缓存例如:
@CachEvict(value=”testcache”,
condition=”#userName.length()>2”)
allEntries是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存例如:
@CachEvict(value=”testcache”,allEntries=true)
beforeInvocation是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存例如:
@CachEvict(value=”testcache”,befo

四、@Configuration 方式配置

由于使用的不是Spring boot 注入属性的值有点不优雅!

import java.lang.reflect.Method;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * <p>
 * RedisCacheConfig描述 redis集成springcache缓存使用
 * </p>
 * 
 * @author lienbo
 * @since 0.0.1
 */
@Component
@EnableCaching
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {

    @Value(value = "${account.redis.hostName}")
    private String hostName;
    @Value(value = "${account.redis.port}")
    private int port;
    @Value(value = "${account.redis.timeout}")
    private int timeout;
    @Value(value = "${account.redis.userPool}")
    private boolean reidsUserPool;

    @Bean
    public JedisConnectionFactory redisConnectionFactory() {
        JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
        // ip地址
        redisConnectionFactory.setHostName(hostName);
        // 端口号
        redisConnectionFactory.setPort(port);
        // 超时时间
        redisConnectionFactory.setTimeout(timeout);
        // 是否开启线程池
        redisConnectionFactory.setUsePool(reidsUserPool);
        // 指定使用的数据库
        redisConnectionFactory.setDatabase(2);
        return redisConnectionFactory;
    }

    /**
     * redisTemplate 序列化使用的jdkSerializeable, 存储二进制字节码, 所以自定义序列化类
     * 
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(
            RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 使用Jackson2JsonRedisSerialize 替换默认序列化
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
                Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL,
            JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        // 设置value的序列化规则和 key的序列化规则
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.cache.annotation.CachingConfigurerSupport#
     * keyGenerator()
     */
    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object o, Method method, Object... objects) {
                StringBuilder sb = new StringBuilder();
                sb.append(o.getClass().getName());
                sb.append(method.getName());
                for (Object obj : objects) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    /**
     * <p>
     * 方法说明
     * </p>
     *
     * @action lienbo 2018年2月2日 下午6:07:24 描述
     *
     * @param redisTemplate
     * @return CacheManager
     */
    @Bean
    public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        // Sets the default expire time (in seconds) Long.
        cacheManager.setDefaultExpiration(3000);
        return cacheManager;
    }
}

五、总结 

以上三种方式是我见到过得redis应用场景,各有有缺,其实不推荐第二种,和代码没有分离,耦合比较深。

个人倾向第一种和第三种,如果完全是缓存,那么三很好有spring这个大树,而第一种可以扩展很多,可以

增加除了缓存的其他逻辑,这是再采用spring cache就显得不恰当了。

转载于:https://my.oschina.net/u/3418748/blog/1504463

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值