在spring boot2之后,对redis连接的支持,默认就采用了lettuce 这就一定程度说明了lettuce 和Jedis的优劣。
1.引入依赖
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
2.application.yml
配置一下redis
服务器的地址
spring:
redis:
host: 127.0.0.1
port: 6379
# 密码 没有则不填
password: 123456
# 连接超时时间
timeout: 10000s
#lettuce配置
lettuce:
pool:
# 最大活跃链接数 默认8
max-active: 8
# 最大空闲连接数 默认8
max-idle: 8
# 最小空闲连接数 默认0
min-idle: 0
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
3.redis配置
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.RedisTemplate;
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.time.Duration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author shuzhuo
* @date 2019/7/30
*/
@Configuration
@Slf4j
public class RedisConfig extends CachingConfigurerSupport {
@Override
public CacheResolver cacheResolver() {
return super.cacheResolver();
}
/**
* 设置自动key的生成规则
* @return
*/
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(":");
sb.append(method.getName());
for (Object obj : params) {
sb.append(":" + String.valueOf(obj));
}
String rsToUse = String.valueOf(sb);
log.info("自动生成Redis Key -> [{}]", rsToUse);
return rsToUse;
};
}
/**
* 打印错误日志
* @return
*/
@Override
public CacheErrorHandler errorHandler() {
log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
}
@Override
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);
}
@Override
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);
}
@Override
public void handleCacheClearError(RuntimeException e, Cache cache) {
log.error("Redis occur handleCacheClearError:", e);
}
};
return cacheErrorHandler;
}
/**
* 配置自定义redisTemplate
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置redisTemplate
RedisTemplate redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
RedisSerializer stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer); // key序列化
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // value序列化
redisTemplate.setHashKeySerializer(stringSerializer); // Hash key序列化
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); // Hash value序列化
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(10))
.disableCachingNullValues()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
//定义 key,这里随便定义3个
String keyName1="keyName1";
String keyName2="keyName2";
String keyName3="keyName3";
// 初始化的缓存空间set集合
Set cacheNames = new HashSet<>();
cacheNames.add(keyName1);
cacheNames.add(keyName2);
cacheNames.add(keyName3);
// 对每个缓存空间应用不同的配置
Map configMap = new HashMap<>();
configMap.put(keyName1, config);
configMap.put(keyName2, config.entryTtl(Duration.ofSeconds(20)));
configMap.put(keyName3, config.entryTtl(Duration.ZERO));
RedisCacheConfiguration defaultConfig = config.entryTtl(Duration.ofSeconds(30));
RedisCacheManager cacheManager = RedisCacheManager.builder(factory) // 使用自定义的缓存配置初始化一个cacheManager
.initialCacheNames(cacheNames) // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
.withInitialCacheConfigurations(configMap)
.cacheDefaults(defaultConfig) //默认配置 //@CachePut 创建的cache 使用默认配置
.build();
log.info("cacheManager init success");
return cacheManager;
}
}
4.测试
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.concurrent.TimeUnit;
/**
* @author shuzhuo
* @date 2019/7/30 15:58
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class RedisTests {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private CacheManager cacheManager;
@Test
public void cacheManagerTest() {
//10s
Cache cache = cacheManager.getCache("keyName1");
if (cache!=null){
cache.put("key1","key1-value");
}
//20s
Cache cache2 = cacheManager.getCache("keyName2");
if (cache2!=null){
cache2.put("key2","key2-value");
}
//永久
Cache cache3 = cacheManager.getCache("keyName3");
if (cache3!=null){
cache3.put("key3","key3-value");
}
// @CachePut 的在接口测试,这里不做测试
}
@Test
public void redisTest() {
// redis存储数据
String key = "shuzhuo-key";
redisTemplate.opsForValue().set(key, "shuzhuo-value", 10, TimeUnit.SECONDS);
// 获取数据
String value = (String) redisTemplate.opsForValue().get(key);
System.out.println("获取缓存中key为" + key + "的值为:" + value);
//SySUser 对象这里不写创建
SySUser user = new SySUser();
user.setUsername("shuzhuo");
user.setId(1);
String userKey = "shuzhuo";
redisTemplate.opsForValue().set(userKey, user, 10, TimeUnit.SECONDS);
SySUser newUser = (SySUser) redisTemplate.opsForValue().get(userKey);
System.out.println("获取缓存中key为" + userKey + "的值为:" + newUser);
}
}
客户端连接查看数据