爲什麼使用Lettuce:
Spring-data-redis提供了在spring應用中通過簡單的配置訪問redis服務,對reids底層開發包(Jedis, JRedis, and RJC)進行了高度封裝
RedisTemplate提供了redis各種操作、異常處理及序列化,支持發佈訂閱,並對spring 3.1 cache進行了實現。
特徵https://spring.io/projects/spring-data-redis
-
RedisTemplate提供了用於執行各種Redis操作,異常轉換和序列化支持的高級抽象。
-
Pubsub支持(例如,消息驅動的POJO的MessageListenerContainer)。
-
JDK,String,JSON和Spring Object / XML映射序列化器。
-
Redis之上的JDK Collection實現。
-
原子計數器支持類。
-
排序和流水線功能。
-
Spring 3.1緩存抽象的Redis 實現。
Spring Data Redis(SDR)框架通過Spring出色的基礎架構支持消除了與存儲庫交互所需的冗餘任務和樣板代碼,從而簡化了編寫使用Redis鍵值存儲庫的Spring應用程序的過程。
redis序列化存儲的問題:
編寫緩存配置類RedisConfig用於調優緩存默認配置,RedisTemplate<String, Object>的類型兼容性更高
大家可以看到在redisTemplate()這個方法中用JacksonJsonRedisSerializer更換掉了Redis默認的序列化方 式:JdkSerializationRedisSerializer
spring-data-redis中序列化類有以下幾個:
GenericToStringSerializer:可以將任何對象泛化爲字符創並序列化
Jackson2JsonRedisSerializer:序列化Object對象爲json字符創(與JacksonJsonRedisSerializer相同)
JdkSerializationRedisSerializer:序列化java 對象 StringRedisSerializer:簡單的字符串序列化
JdkSerializationRedisSerializer序列化被序列化對象必須實現Serializable接口,被序列化除屬性內容還有其他內容,長度長且不易閱讀,默認就是採用這種序列化方式
存儲內容如下:
"\xac\xed\x00\x05sr\x00!com.oreilly.springdata.redis.User\xb1\x1c
\n\xcd\xed%\xd8\x02\x00\x02I\x00\x03ageL\x00\buserNamet\x00\x12Ljava/lang/String;xp\x00\x00\x00\ x14t\x00\x05user1"
JacksonJsonRedisSerializer序列化,被序列化對象不需要實現Serializable接口,被序列化的結果清晰,容易閱讀,而且存儲字節少,速度快
存儲內容如下:
"{"userName":"guoweixin","age":20}"
StringRedisSerializer序列化
一般如果key、value都是string字符串的話,就是用這個就可以了
項目目錄:
一、pom文件,引入依賴
<!--Spring Data Redis 默認是lettuce客戶端-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--redis依賴pool連接池這個jar包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.7.0</version>
</dependency>
配置文件:application.yml
server:
port: 8889
#redis
spring:
redis:
port: 6379
password: Xxf159357!_
host: 182.92.236.141
lettuce:
pool:
max-active: 100 # 連接池最大連接數(使用負值表示沒有限制) 太小可能出現connection.PoolExcelption
max-idle: 8 # 連接池中的最大空閒連接
min-idle: 0 # 連接池中的最小空閒連接
max-wait: 1000 # 連接池最大阻塞等待時間(使用負值表示沒有限制)
shutdown-timeout: 100 # 關閉超時時間
#log 出現<font color=red>CONDITIONS EVALUATION REPORT</font>
#<font color=red>java.lang.IllegalStateException: Failed to load ApplicationContext</font>釋放下面代碼
#logging.level.org.springframework.boot.autoconfigure: error
#logging:
#level: info
二、RedisConfig類
package com.xxf.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
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.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.lang.reflect.Method;
/**
* @Author:xuefengxia
* @Date:2020/6/18
* @Description:
*/
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
/**
* 自定義緩存key的生成策略。默認的生成策略是看不懂的(亂碼內容)
* 通過Spring 的依賴注入特性進行自定義的配置注入並且此類是一個配置類可以更多程度的自定義配置
* @return
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
/**
* 緩存配置管理器
*/
@Bean
public CacheManager cacheManager(LettuceConnectionFactory factory) {
//以鎖寫入的方式創建RedisCacheWriter對象
RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(factory);
//創建默認緩存配置對象
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheManager cacheManager = new RedisCacheManager(writer, config);
return cacheManager;
}
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
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);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// 在使用註解@Bean返回RedisTemplate的時候,同時配置hashKey與hashValue的序列化方式。
// key採用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// value 序 列 化 方 式 採 用 jackson
//使用它操作普通字符串,會出現Could not read JSON template.setValueSerializer(jackson2JsonRedisSerializer);
template.setValueSerializer(stringRedisSerializer);
// hash的key也採用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// hash的value序列化方式採用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
三、實例RedisServImpl
package com.xxf.service;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
/**
* @Author:xuefeng
* @Date:2020/6/18
* @Description:
*/
@Service
@Log
public class RedisServiceImpl {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
/**
*普通緩存放入
*@param key 鍵
*@return true成功 false失敗
*/
public String getString(String key) {
if(redisTemplate.hasKey(key)) {
log.info("Redis中查詢");
redisTemplate.opsForValue().set("jsonStr","{'userName':'xxf','age':20}");
System.out.println(redisTemplate.opsForValue().get(key));
return (String) redisTemplate.opsForValue().get(key);
}else{
String val="xxf";
redisTemplate.opsForValue().set(key, val);
log.info("數據庫中查詢的");
return val;
}
}
/**
*普通緩存放入
*@param key 鍵
*@param value 值
*@param expireTime 超時時間(秒)
*@return true成功 false失敗
*/
public Boolean set(String key, Object value, int expireTime) {
try {
redisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.SECONDS);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
四、測試類
package com.xxf.lettuce;
import com.xxf.service.RedisServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
/**
* @Author:xuefeng
* @Date:2020/6/18
* @Description:
*/
@SpringBootTest
class TestRedisTemplate {
@Autowired
private RedisServiceImpl redisService;
@Test
public void testGetKey() {
redisService.getString("jsonStr");
}
@Test
public void testSetKey() {
redisService.set("xxf","黎明的光與影",5000);
}
}