springboot 整合 redis
source:?www.cnblogs.com/cool-fun/p/15707666.html
簡介:在SpringBoot中一般使用RedisTemplate提供的方法來操作Redis。那么使用SpringBoot整合Redis需要哪些步驟呢。
1. JedisPoolConfig (配置連接池)
2. RedisConnectionFactory 這個是配置連接信息,這里的RedisConnectionFactory是一個接 口,我們需要使用它的實現(xiàn)類,在SpringD Data Redis方案中提供了以下四種工廠模型:
JredisConnectionFactory
JedisConnectionFactory
LettuceConnectionFactory
SrpConnectionFactory
3.?RedisTemplate基本操作
導入依賴
<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
測試
@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 自動配置類
@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;
????}
}
通過源碼可以看出,SpringBoot自動幫我們在容器中生成了一個RedisTemplate和一個 StringRedisTemplate。
但是,這個RedisTemplate的泛型是,寫代碼不方便,需要寫好多類型轉換的代碼;我 們需要一個泛型為形式的RedisTemplate。
并且,這個RedisTemplate沒有設置數(shù)據(jù)存在Redis時,key及value的序列化方式。
看到這個@ConditionalOnMissingBean注解后,就知道如果Spring容器中有了RedisTemplate對象了, 這個自動配置的RedisTemplate不會實例化。因此我們可以直接自己寫個配置類,配置 RedisTemplate。
既然自動配置不好用,就重新配置一個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等會跑出異常
????????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;
????}
}
寫一個Redis工具類(直接用RedisTemplate操作Redis,需要很多行代碼,因此直接封裝好一個 RedisUtils,這樣寫代碼更方便點。這個RedisUtils交給Spring容器實例化,使用時直接注解注入。)
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============================
????/**
?????*?指定緩存失效時間
?????*
?????*?@param?key??鍵
?????*?@param?time?時間(秒)
?????*/
????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?獲取過期時間
?????*
?????*?@param?key?鍵?不能為null
?????*?@return?時間(秒)?返回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?可以傳一個值?或多個
?????*/
????@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;
????????}
????}
????/**
?????*?普通緩存放入并設置時間
?????*
?????*?@param?key???鍵
?????*?@param?value?值
?????*?@param?time??時間(秒)?time要大于0?如果time小于等于0?將設置無限期
?????*?@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?項?不能為null
?????*/
????public?Object?hget(String?key,?String?item)?{
????????return?redisTemplate.opsForHash().get(key,?item);
????}
????/**
?????*?獲取hashKey對應的所有鍵值
?????*
?????*?@param?key?鍵
?????*?@return?對應的多個鍵值
?????*/
????public?Map{
????????return?redisTemplate.opsForHash().entries(key);
????}
????/**
?????*?HashSet
?????*
?????*?@param?key?鍵
?????*?@param?map?對應多個鍵值
?????*/
????public?boolean?hmset(String?key,?Map?map) ?{
????????try?{
????????????redisTemplate.opsForHash().putAll(key,?map);
????????????return?true;
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?false;
????????}
????}
????/**
?????*?HashSet?并設置時間
?????*
?????*?@param?key??鍵
?????*?@param?map??對應多個鍵值
?????*?@param?time?時間(秒)
?????*?@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??項
?????*?@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??項
?????*?@param?value?值
?????*?@param?time??時間(秒)?注意:如果已存在的hash表有時間,這里將會替換原有的時間
?????*?@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?項?可以使多個?不能為null
?????*/
????public?void?hdel(String?key,?Object...?item)?{
????????redisTemplate.opsForHash().delete(key,?item);
????}
????/**
?????*?判斷hash表中是否有該項的值
?????*
?????*?@param?key??鍵?不能為null
?????*?@param?item?項?不能為null
?????*?@return?true?存在?false不存在
?????*/
????public?boolean?hHasKey(String?key,?String?item)?{
????????return?redisTemplate.opsForHash().hasKey(key,?item);
????}
????/**
?????*?hash遞增?如果不存在,就會創(chuàng)建一個?并把新增后的值返回
?????*
?????*?@param?key??鍵
?????*?@param?item?項
?????*?@param?by???要增加幾(大于0)
?????*/
????public?double?hincr(String?key,?String?item,?double?by)?{
????????return?redisTemplate.opsForHash().increment(key,?item,?by);
????}
????/**
?????*?hash遞減
?????*
?????*?@param?key??鍵
?????*?@param?item?項
?????*?@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從一個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?值?可以是多個
?????*?@return?成功個數(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???時間(秒)
?????*?@param?values?值?可以是多個
?????*?@return?成功個數(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緩存的長度
?????*
?????*?@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?值?可以是多個
?????*?@return?移除的個數(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?開始
?????*?@param?end???結束?0?到?-1代表所有值
?????*/
????public?List{
????????try?{
????????????return?redisTemplate.opsForList().range(key,?start,?end);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?null;
????????}
????}
????/**
?????*?獲取list緩存的長度
?????*
?????*?@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?值?可以是多個
?????*?@return?移除的個數(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?開始
?????*?@param?end???結束?0?到?-1代表所有值
?????*/
????public?List{
????????try?{
????????????return?redisTemplate.opsForList().range(key,?start,?end);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?null;
????????}
????}
????/**
?????*?獲取list緩存的長度
?????*
?????*?@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?值?可以是多個
?????*?@return?移除的個數(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?開始
?????*?@param?end???結束?0?到?-1代表所有值
?????*/
????public?List{
????????try?{
????????????return?redisTemplate.opsForList().range(key,?start,?end);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?null;
????????}
????}
????/**
?????*?獲取list緩存的長度
?????*
?????*?@param?key?鍵
?????*/
????public?long?lGetListSize(String?key)?{
????????try?{
????????????return?redisTemplate.opsForList().size(key);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????return?0;
????????}
????}
????/**
?????*?通過索引?獲取list中的值
?????*
?????*?@param?key???鍵
?????*?@param?index 索引 index>=0時,?0?表頭,1 第二個元素,依次類推;index<0
?????*??????????????時,-1,表尾,-2倒數(shù)第二個元素,依次類推
?????*/
????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??時間(秒)
?????*/
????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??時間(秒)
?????*?@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個值為value
?????*
?????*?@param?key???鍵
?????*?@param?count?移除多少個
?????*?@param?value?值
?????*?@return?移除的個數(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;
????????}
????}
}

喜歡,在看
