springboot 整合 redis
source:?www.cnblogs.com/cool-fun/p/15707666.html
簡(jiǎn)介:在SpringBoot中一般使用RedisTemplate提供的方法來(lái)操作Redis。那么使用SpringBoot整合Redis需要哪些步驟呢。
1. JedisPoolConfig (配置連接池)
2. RedisConnectionFactory 這個(gè)是配置連接信息,這里的RedisConnectionFactory是一個(gè)接 口,我們需要使用它的實(shí)現(xiàn)類,在SpringD Data Redis方案中提供了以下四種工廠模型:
JredisConnectionFactory
JedisConnectionFactory
LettuceConnectionFactory
SrpConnectionFactory
3.?RedisTemplate基本操作
導(dǎo)入依賴
<dependency>
???<groupId>org.springframework.bootgroupId>
???<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
yml配置
spring:
??redis:
???host:?127.0.0.1
???port:?6379
???password:?123456
???jedis:
?????pool:
??????max-active:?8
??????max-wait:?-1ms
??????max-idle:?500
??????min-idle:?0
???lettuce:
?????shutdown-timeout:?0ms
測(cè)試
@SpringBootTest
class?SpringbootRedisApplicationTests?{
????@Autowired
????private?RedisTemplate<String,?String>?redisTemplate;
????@Test
????void?contextLoads()?{
????????redisTemplate.opsForValue().set("myKey",?"myValue");
????????System.out.println(redisTemplate.opsForValue().get("myKey"));
????}
}
分析 RedisAutoConfiguration 自動(dòng)配置類
@Configuration(proxyBeanMethods?=?false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({LettuceConnectionConfiguration.class,?JedisConnectionConfiguration.class})
public?class?RedisAutoConfiguration?{
????@Bean
????@ConditionalOnMissingBean(name?=?"redisTemplate")
????public?RedisTemplate<Object,?Object>?redisTemplate(RedisConnectionFactory?redisConnectionFactory)
????????????throws?UnknownHostException?{
????????RedisTemplate<Object,?Object>?template?=?new?RedisTemplate<>();
????????template.setConnectionFactory(redisConnectionFactory);
????????return?template;
????}
????@Bean
????@ConditionalOnMissingBean
????public?StringRedisTemplate?stringRedisTemplate(RedisConnectionFactory
???????????????????????????????????????????????????????????redisConnectionFactory)?throws?UnknownHostException?{
????????StringRedisTemplate?template?=?new?StringRedisTemplate();
????????template.setConnectionFactory(redisConnectionFactory);
????????return?template;
????}
}
通過(guò)源碼可以看出,SpringBoot自動(dòng)幫我們?cè)谌萜髦猩闪艘粋€(gè)RedisTemplate和一個(gè) StringRedisTemplate。
但是,這個(gè)RedisTemplate的泛型是,寫(xiě)代碼不方便,需要寫(xiě)好多類型轉(zhuǎn)換的代碼;我 們需要一個(gè)泛型為形式的RedisTemplate。
并且,這個(gè)RedisTemplate沒(méi)有設(shè)置數(shù)據(jù)存在Redis時(shí),key及value的序列化方式。
看到這個(gè)@ConditionalOnMissingBean注解后,就知道如果Spring容器中有了RedisTemplate對(duì)象了, 這個(gè)自動(dòng)配置的RedisTemplate不會(huì)實(shí)例化。因此我們可以直接自己寫(xiě)個(gè)配置類,配置 RedisTemplate。
既然自動(dòng)配置不好用,就重新配置一個(gè)RedisTemplate
import?org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import?org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public?class?RedisConfig?{
????@Bean
????@SuppressWarnings("all")
????public?RedisTemplate<String,?Object>?redisTemplate(RedisConnectionFactory?factory)?{
????????RedisTemplate<String,?Object>?template?=?new?RedisTemplate<String,?Object>();
????????template.setConnectionFactory(factory);
????????Jackson2JsonRedisSerializer?jackson2JsonRedisSerializer?=?new
????????????????Jackson2JsonRedisSerializer(Object.class);
????????ObjectMapper?om?=?new?ObjectMapper();
????????om.setVisibility(PropertyAccessor.ALL,?JsonAutoDetect.Visibility.ANY);
????????//?指定序列化輸入的類型,類必須是非final修飾的,final修飾的類,比如String,Integer等會(huì)跑出異常
????????om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,??ObjectMapper.DefaultTyping.NON_FINAL);
????????jackson2JsonRedisSerializer.setObjectMapper(om);
????????StringRedisSerializer?stringRedisSerializer?=?new
????????????????StringRedisSerializer();
????????//?key采用String的序列化方式
????????template.setKeySerializer(stringRedisSerializer);
????????//?hash的key也采用String的序列化方式
????????template.setHashKeySerializer(stringRedisSerializer);
????????//?value序列化方式采用jackson
????????template.setValueSerializer(jackson2JsonRedisSerializer);
?????????//?hash的value序列化方式采用jackson
????????template.setHashValueSerializer(jackson2JsonRedisSerializer);
????????template.afterPropertiesSet();
????????return?template;
????}
}
寫(xiě)一個(gè)Redis工具類(直接用RedisTemplate操作Redis,需要很多行代碼,因此直接封裝好一個(gè) RedisUtils,這樣寫(xiě)代碼更方便點(diǎn)。這個(gè)RedisUtils交給Spring容器實(shí)例化,使用時(shí)直接注解注入。)
package?com.olive.utils;
import?org.springframework.beans.factory.annotation.Autowired;
import?org.springframework.data.redis.core.RedisTemplate;
import?org.springframework.stereotype.Component;
import?org.springframework.util.CollectionUtils;
import?java.util.List;
import?java.util.Map;
import?java.util.Set;
import?java.util.concurrent.TimeUnit;
@Component
public?final?class?RedisUtil?{
????@Autowired
????private?RedisTemplate?redisTemplate;
//?=============================common============================
????/**
?????*?指定緩存失效時(shí)間
?????*
?????*?@param?key??鍵
?????*?@param?time?時(shí)間(秒)
?????*/
????public?boolean?expire(String?key,?long?time)?{
????????try?{
????????????if?(time?>?0)?{
????????????????redisTemplate.expire(key,?time,?TimeUnit.SECONDS);
????????????}
????????????return?true;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?根據(jù)key?獲取過(guò)期時(shí)間
?????*
?????*?@param?key?鍵?不能為null
?????*?@return?時(shí)間(秒)?返回0代表為永久有效
?????*/
????public?long?getExpire(String?key)?{
????????return?redisTemplate.getExpire(key,?TimeUnit.SECONDS);
????}
????/**
?????*?判斷key是否存在
?????*
?????*?@param?key?鍵
?????*?@return?true?存在?false不存在
?????*/
????public?boolean?hasKey(String?key)?{
????????try?{
????????????return?redisTemplate.hasKey(key);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?刪除緩存
?????*
?????*?@param?key?可以傳一個(gè)值?或多個(gè)
?????*/
????@SuppressWarnings("unchecked")
????public?void?del(String...?key)?{
????????if?(key?!=?null?&&?key.length?>?0)?{
????????????if?(key.length?==?1)?{
????????????????redisTemplate.delete(key[0]);
????????????}?else?{
????????????????redisTemplate.delete(CollectionUtils.arrayToList(key));
????????????}
????????}
????}
//?============================String=============================
????/**
?????*?普通緩存獲取
?????*
?????*?@param?key?鍵
?????*?@return?值
?????*/
????public?Object?get(String?key)?{
????????return?key?==?null???null?:?redisTemplate.opsForValue().get(key);
????}
????/**
?????*?普通緩存放入
?????*
?????*?@param?key???鍵
?????*?@param?value?值
?????*?@return?true成功?false失敗
?????*/
????public?boolean?set(String?key,?Object?value)?{
????????try?{
????????????redisTemplate.opsForValue().set(key,?value);
????????????return?true;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?普通緩存放入并設(shè)置時(shí)間
?????*
?????*?@param?key???鍵
?????*?@param?value?值
?????*?@param?time??時(shí)間(秒)?time要大于0?如果time小于等于0?將設(shè)置無(wú)限期
?????*?@return?true成功?false?失敗
?????*/
????public?boolean?set(String?key,?Object?value,?long?time)?{
????????try?{
????????????if?(time?>?0)?{
????????????????redisTemplate.opsForValue().set(key,?value,?time,
????????????????????????TimeUnit.SECONDS);
????????????}?else?{
????????????????set(key,?value);
????????????}
????????????return?true;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?遞增
?????*
?????*?@param?key???鍵
?????*?@param?delta?要增加幾(大于0)
?????*/
????public?long?incr(String?key,?long?delta)?{
????????if?(delta?0)?{
????????????throw?new?RuntimeException("遞增因子必須大于0");
????????}
????????return?redisTemplate.opsForValue().increment(key,?delta);
????}
????/**
?????*?遞減
?????*
?????*?@param?key???鍵
?????*?@param?delta?要減少幾(小于0)
?????*/
????public?long?decr(String?key,?long?delta)?{
????????if?(delta?0)?{
????????????throw?new?RuntimeException("遞減因子必須大于0");
????????}
????????return?redisTemplate.opsForValue().increment(key,?-delta);
????}
//?================================Map=================================
????/**
?????*?HashGet
?????*
?????*?@param?key??鍵?不能為null
?????*?@param?item?項(xiàng)?不能為null
?????*/
????public?Object?hget(String?key,?String?item)?{
????????return?redisTemplate.opsForHash().get(key,?item);
????}
????/**
?????*?獲取hashKey對(duì)應(yīng)的所有鍵值
?????*
?????*?@param?key?鍵
?????*?@return?對(duì)應(yīng)的多個(gè)鍵值
?????*/
????public?Map{
????????return?redisTemplate.opsForHash().entries(key);
????}
????/**
?????*?HashSet
?????*
?????*?@param?key?鍵
?????*?@param?map?對(duì)應(yīng)多個(gè)鍵值
?????*/
????public?boolean?hmset(String?key,?Map?map) ?{
????????try?{
????????????redisTemplate.opsForHash().putAll(key,?map);
????????????return?true;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?HashSet?并設(shè)置時(shí)間
?????*
?????*?@param?key??鍵
?????*?@param?map??對(duì)應(yīng)多個(gè)鍵值
?????*?@param?time?時(shí)間(秒)
?????*?@return?true成功?false失敗
?????*/
????public?boolean?hmset(String?key,?Map?map,?long?time) ?{
????????try?{
????????????redisTemplate.opsForHash().putAll(key,?map);
????????????if?(time?>?0)?{
????????????????expire(key,?time);
????????????}
????????????return?true;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?向一張hash表中放入數(shù)據(jù),如果不存在將創(chuàng)建
?????*
?????*?@param?key???鍵
?????*?@param?item??項(xiàng)
?????*?@param?value?值
?????*?@return?true?成功?false失敗
?????*/
????public?boolean?hset(String?key,?String?item,?Object?value)?{
????????try?{
????????????redisTemplate.opsForHash().put(key,?item,?value);
????????????return?true;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?向一張hash表中放入數(shù)據(jù),如果不存在將創(chuàng)建
?????*
?????*?@param?key???鍵
?????*?@param?item??項(xiàng)
?????*?@param?value?值
?????*?@param?time??時(shí)間(秒)?注意:如果已存在的hash表有時(shí)間,這里將會(huì)替換原有的時(shí)間
?????*?@return?true?成功?false失敗
?????*/
????public?boolean?hset(String?key,?String?item,?Object?value,?long?time)?{
????????try?{
????????????redisTemplate.opsForHash().put(key,?item,?value);
????????????if?(time?>?0)?{
????????????????expire(key,?time);
????????????}
????????????return?true;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?刪除hash表中的值
?????*
?????*?@param?key??鍵?不能為null
?????*?@param?item?項(xiàng)?可以使多個(gè)?不能為null
?????*/
????public?void?hdel(String?key,?Object...?item)?{
????????redisTemplate.opsForHash().delete(key,?item);
????}
????/**
?????*?判斷hash表中是否有該項(xiàng)的值
?????*
?????*?@param?key??鍵?不能為null
?????*?@param?item?項(xiàng)?不能為null
?????*?@return?true?存在?false不存在
?????*/
????public?boolean?hHasKey(String?key,?String?item)?{
????????return?redisTemplate.opsForHash().hasKey(key,?item);
????}
????/**
?????*?hash遞增?如果不存在,就會(huì)創(chuàng)建一個(gè)?并把新增后的值返回
?????*
?????*?@param?key??鍵
?????*?@param?item?項(xiàng)
?????*?@param?by???要增加幾(大于0)
?????*/
????public?double?hincr(String?key,?String?item,?double?by)?{
????????return?redisTemplate.opsForHash().increment(key,?item,?by);
????}
????/**
?????*?hash遞減
?????*
?????*?@param?key??鍵
?????*?@param?item?項(xiàng)
?????*?@param?by???要減少記(小于0)
?????*/
????public?double?hdecr(String?key,?String?item,?double?by)?{
????????return?redisTemplate.opsForHash().increment(key,?item,?-by);
????}
//?============================set=============================
????/**
?????*?根據(jù)key獲取Set中的所有值
?????*
?????*?@param?key?鍵
?????*/
????public?Set{
????????try?{
????????????return?redisTemplate.opsForSet().members(key);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?null;
????????}
????}
????/**
?????*?根據(jù)value從一個(gè)set中查詢,是否存在
?????*
?????*?@param?key???鍵
?????*?@param?value?值
?????*?@return?true?存在?false不存在
?????*/
????public?boolean?sHasKey(String?key,?Object?value)?{
????????try?{
????????????return?redisTemplate.opsForSet().isMember(key,?value);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?將數(shù)據(jù)放入set緩存
?????*
?????*?@param?key????鍵
?????*?@param?values?值?可以是多個(gè)
?????*?@return?成功個(gè)數(shù)
?????*/
????public?long?sSet(String?key,?Object...?values)?{
????????try?{
????????????return?redisTemplate.opsForSet().add(key,?values);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?0;
????????}
????}
????/**
?????*?將set數(shù)據(jù)放入緩存
?????*
?????*?@param?key????鍵
?????*?@param?time???時(shí)間(秒)
?????*?@param?values?值?可以是多個(gè)
?????*?@return?成功個(gè)數(shù)
?????*/
????public?long?sSetAndTime(String?key,?long?time,?Object...?values)?{
????????try?{
????????????Long?count?=?redisTemplate.opsForSet().add(key,?values);
????????????if?(time?>?0)
????????????????expire(key,?time);
????????????return?count;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?0;
????????}
????}
????/**
?????*?獲取set緩存的長(zhǎng)度
?????*
?????*?@param?key?鍵
?????*/
????public?long?sGetSetSize(String?key)?{
????????try?{
????????????return?redisTemplate.opsForSet().size(key);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?0;
????????}
????}
????/**
?????*?移除值為value的
?????*
?????*?@param?key????鍵
?????*?@param?values?值?可以是多個(gè)
?????*?@return?移除的個(gè)數(shù)
?????*/
????public?long?setRemove(String?key,?Object...?values)?{
????????try?{
????????????Long?count?=?redisTemplate.opsForSet().remove(key,?values);
????????????return?count;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?0;
????????}
????}
//?===============================list=================================
????/**
?????*?獲取list緩存的內(nèi)容
?????*
?????*?@param?key???鍵
?????*?@param?start?開(kāi)始
?????*?@param?end???結(jié)束?0?到?-1代表所有值
?????*/
????public?List{
????????try?{
????????????return?redisTemplate.opsForList().range(key,?start,?end);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?null;
????????}
????}
????/**
?????*?獲取list緩存的長(zhǎng)度
?????*
?????*?@param?key?鍵
?????*/
????public?long?sGetSetSize(String?key)?{
????????try?{
????????????return?redisTemplate.opsForSet().size(key);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?0;
????????}
????}
????/**
?????*?移除值為value的
?????*
?????*?@param?key????鍵
?????*?@param?values?值?可以是多個(gè)
?????*?@return?移除的個(gè)數(shù)
?????*/
????public?long?setRemove(String?key,?Object...?values)?{
????????try?{
????????????Long?count?=?redisTemplate.opsForSet().remove(key,?values);
????????????return?count;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?0;
????????}
????}
//?===============================list=================================
????/**
?????*?獲取list緩存的內(nèi)容
?????*
?????*?@param?key???鍵
?????*?@param?start?開(kāi)始
?????*?@param?end???結(jié)束?0?到?-1代表所有值
?????*/
????public?List{
????????try?{
????????????return?redisTemplate.opsForList().range(key,?start,?end);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?null;
????????}
????}
????/**
?????*?獲取list緩存的長(zhǎng)度
?????*
?????*?@param?key?鍵
?????*/
????public?long?lGetListSize(String?key)?{
????????try?{
????????????return?redisTemplate.opsForList().size(key);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?0;
????????}
????}
????/**
?????*?移除值為value的
?????*
?????*?@param?key????鍵
?????*?@param?values?值?可以是多個(gè)
?????*?@return?移除的個(gè)數(shù)
?????*/
????public?long?setRemove(String?key,?Object...?values)?{
????????try?{
????????????Long?count?=?redisTemplate.opsForSet().remove(key,?values);
????????????return?count;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?0;
????????}
????}
//?===============================list=================================
????/**
?????*?獲取list緩存的內(nèi)容
?????*
?????*?@param?key???鍵
?????*?@param?start?開(kāi)始
?????*?@param?end???結(jié)束?0?到?-1代表所有值
?????*/
????public?List{
????????try?{
????????????return?redisTemplate.opsForList().range(key,?start,?end);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?null;
????????}
????}
????/**
?????*?獲取list緩存的長(zhǎng)度
?????*
?????*?@param?key?鍵
?????*/
????public?long?lGetListSize(String?key)?{
????????try?{
????????????return?redisTemplate.opsForList().size(key);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?0;
????????}
????}
????/**
?????*?通過(guò)索引?獲取list中的值
?????*
?????*?@param?key???鍵
?????*?@param?index 索引 index>=0時(shí),?0?表頭,1 第二個(gè)元素,依次類推;index<0
?????*??????????????時(shí),-1,表尾,-2倒數(shù)第二個(gè)元素,依次類推
?????*/
????public?Object?lGetIndex(String?key,?long?index)?{
????????try?{
????????????return?redisTemplate.opsForList().index(key,?index);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?null;
????????}
????}
????/**
?????*?將list放入緩存
?????*
?????*?@param?key???鍵
?????*?@param?value?值
?????*/
????public?boolean?lSet(String?key,?Object?value)?{
????????try?{
????????????redisTemplate.opsForList().rightPush(key,?value);
????????????return?true;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?將list放入緩存
?????*
?????*?@param?key???鍵
?????*?@param?value?值
?????*?@param?time??時(shí)間(秒)
?????*/
????public?boolean?lSet(String?key,?Object?value,?long?time)?{
????????try?{
????????????redisTemplate.opsForList().rightPush(key,?value);
????????????if?(time?>?0)
????????????????expire(key,?time);
????????????return?true;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?將list放入緩存
?????*
?????*?@param?key???鍵
?????*?@param?value?值
?????*?@return
?????*/
????public?boolean?lSet(String?key,?List?{
????????try?{
????????????redisTemplate.opsForList().rightPushAll(key,?value);
????????????return?true;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?將list放入緩存
?????*
?????*?@param?key???鍵
?????*?@param?value?值
?????*?@param?time??時(shí)間(秒)
?????*?@return
?????*/
????public?boolean?lSet(String?key,?List?{
????????try?{
????????????redisTemplate.opsForList().rightPushAll(key,?value);
????????????if?(time?>?0)
????????????????expire(key,?time);
????????????return?true;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?根據(jù)索引修改list中的某條數(shù)據(jù)
?????*
?????*?@param?key???鍵
?????*?@param?index?索引
?????*?@param?value?值
?????*?@return
?????*/
????public?boolean?lUpdateIndex(String?key,?long?index,?Object?value)?{
????????try?{
????????????redisTemplate.opsForList().set(key,?index,?value);
????????????return?true;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?移除N個(gè)值為value
?????*
?????*?@param?key???鍵
?????*?@param?count?移除多少個(gè)
?????*?@param?value?值
?????*?@return?移除的個(gè)數(shù)
?????*/
????public?long?lRemove(String?key,?long?count,?Object?value)?{
????????try?{
????????????Long?remove?=?redisTemplate.opsForList().remove(key,?count,?value);
????????????return?remove;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?0;
????????}
????}
}

喜歡,在看
