一、前期准备
- 一个构建好的springboot系统
- 下载redis安装包,去redis官网下载
- 启动redis服务,windows下双击bin目录下的redis-service.exe
二、环境构建
- 在项目的
pom.xml
中引入redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 在项目配置文件
application.yml
中添加redis配置
spring:
#redis缓存
redis:
open: true # 是否开启redis缓存 true开启 false关闭
database: 0
host: 127.0.0.1
port: 6379
password: # 密码(默认为空)
timeout: 60000ms # 连接超时时长(毫秒)
jedis:
pool:
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
三、redis手动缓存
1、缓存配置
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.time.Duration;
/**
* 缓存配置类
* @author 谢小鱼
* @Date 2019-11-20 11:00
**/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
@Bean
public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
return redisTemplate.opsForValue();
}
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}
四、redis注解缓存
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.time.Duration;
/**
* 缓存配置类
* @author 谢小鱼
* @Date 2019-11-20 11:00
**/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);
@Autowired
private RedisConnectionFactory factory;
/**
* 默认两小时
*/
private static final long DURATION_SECOND_7200 = 7200L;
private static final long DURATION_SECOND_300 = 300L;
@Override
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@SuppressWarnings("rawtypes")
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder(RedisAutoCacheValue.AUTO_KEY_PREFIX);
if(target instanceof Proxy) {
//如果是代理类
Class[] i = target.getClass().getInterfaces();
if(i != null && i.length > 0) {
//取第一个即可
sb.append(i[0].getName());
}else {
sb.append(target.getClass().getName());
}
} else if(target instanceof org.springframework.cglib.proxy.Factory){
//如果是cglib代理,需要手动去除 $$ 后面的
String className = target.getClass().getName();
sb.append(className, 0, className.indexOf("$$"));
} else {
sb.append(target.getClass().getName());
}
sb.append(".");
sb.append(method.getName());
sb.append("_");
for (Object obj : params) {
if (obj != null) {
Class cls = obj.getClass();
if (cls.isArray()) {
//对于基础数据处理
logger.info("keyGenerator : {}", cls.getComponentType());
if (cls.isAssignableFrom(long.class)) {
long[] ay = (long[]) obj;
for (long o : ay) {
sb.append(o).append("");
}
} else if (cls.isAssignableFrom(int.class)) {
int[] ay = (int[]) obj;
for (int o : ay) {
sb.append(o).append("");
}
} else if (cls.isAssignableFrom(float.class)) {
float[] ay = (float[]) obj;
for (float o : ay) {
sb.append(o).append("");
}
} else if (cls.isAssignableFrom(double.class)) {
double[] ay = (double[]) obj;
for (double o : ay) {
sb.append(o).append("");
}
} else if (cls.isAssignableFrom(String.class)) {
String[] ay = (String[]) obj;
for (String o : ay) {
sb.append(o).append("");
}
} else {
sb.append(obj.toString());
}
//TODO 对其他类型数组处理
} else {
sb.append(obj.toString());
}
} else {
sb.append("null");
}
sb.append("_");
//sb.append(obj == null ? "null" : obj.toString());
}
sb.delete(sb.length()-1, sb.length());
return sb.toString();
}
};
}
/**
* 默认的缓存管理,存放时效较长的缓存
* @param redisTemplate
* @return
*/
@SuppressWarnings({"rawtypes", "Duplicates"})
@Primary
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheConfiguration config = RedisCacheConfiguration
.defaultCacheConfig()
//过期时间
.entryTtl(Duration.ofSeconds(DURATION_SECOND_7200))
//不缓存null值
//.disableCachingNullValues()
//明确manager中的序列化与template一样,防止莫名其妙的问题
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(this.keySerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(this.valueSerializer()));
RedisCacheManager rcm = RedisCacheManager.builder(redisTemplate.getConnectionFactory()).cacheDefaults(config).transactionAware().build();
return rcm;
}
/**
* 存放时效较短的缓存(5分钟)
* @param redisTemplate
* @return
*/
@SuppressWarnings({"rawtypes", "Duplicates"})
@Bean
public CacheManager cacheManagerIn5Minutes(RedisTemplate redisTemplate) {
RedisCacheConfiguration config = RedisCacheConfiguration
.defaultCacheConfig()
//过期时间
.entryTtl(Duration.ofSeconds(DURATION_SECOND_300))
//不缓存null值
//.disableCachingNullValues()
//明确manager中的序列化与template一样,防止莫名其妙的问题
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(this.keySerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(this.valueSerializer()));
RedisCacheManager rcm = RedisCacheManager.builder(redisTemplate.getConnectionFactory()).cacheDefaults(config).transactionAware().build();
return rcm;
}
private RedisSerializer<String> keySerializer() {
return new StringRedisSerializer();
}
private RedisSerializer<Object> valueSerializer() {
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//略过不匹配的属性
om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
jackson2JsonRedisSerializer.setObjectMapper(om);
return jackson2JsonRedisSerializer;
}
}
自动缓存key:
/**
* 自动缓存value集中在此
* @author Leon
* @Date 2019-11-19 12:38
**/
public class RedisAutoCacheValue {
/**
* 自动生成key前缀
*/
public static final String AUTO_KEY_PREFIX = "AUTO:";
}
推荐使用注解的方式操作redis,便于维护