SpringBoot整合Redis-
SpringBoot整合Redis–RedisTemplate
1、导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、编写配置文件
spring:
redis:
host: 192.168.27.132
port: 6379
password: lzyredis
database: 1
jedis:
pool:
max-active: 10
max-wait: 3000
min-idle: 5
max-idle: 10
3、测试代码
RedisTemplate.opsForXxx().操作
- Xxx:代表要操作的数据类型【value代表操作的是string】
@SpringBootTest
class SpringbootRedisDemoApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void test(){
//setIfAbsent 就是 setnx
Boolean absent = redisTemplate.opsForValue().setIfAbsent("name", "xiaoming", 5 * 60, SECONDS);
System.out.println("absent = " + absent);
String name = (String) redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
}
springboot整合redis测试后存储的数据 |
---|
打印结果 |
在第一张图中发现存储的key和value前出现了一些不认识的字符,虽然在RedisDesktopManager工具上显示不是期望的格式,但在打印结果上看却是正常显示的。
这是因为使用RedisTemplate来操作字符串时,在存储数据时会对key和value进行序列化操作。
序列化操作会对选择对应的序列化器来操作,如果没有指定序列化器,那么默认选择是JDK序列化器。
所以会出现一长串字符串。
4、RedisTemplate选择序列化器的原理:
RedisTemplate
继承RedisAccessor
类,而该类实现了InitializingBean
接口,所以
RedisTemplate
会调用afterPropertiesSet
方法。在该方法中会对操作key和value进行序列化操作,
如果指定了具体的序列化器,那么就会使用指定的序列化器,
如果没有指定具体的序列化器,则使用JDK序列化器
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
if (this.defaultSerializer == null) {
//没有指定的序列化器,那默认序列化器就为jdk序列化器
this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());
}
if (this.enableDefaultSerializer) {
if (this.keySerializer == null) {
this.keySerializer = this.defaultSerializer;
defaultUsed = true;
}
if (this.valueSerializer == null) {
this.valueSerializer = this.defaultSerializer;
defaultUsed = true;
}
if (this.hashKeySerializer == null) {
this.hashKeySerializer = this.defaultSerializer;
defaultUsed = true;
}
if (this.hashValueSerializer == null) {
this.hashValueSerializer = this.defaultSerializer;
defaultUsed = true;
}
}
if (this.enableDefaultSerializer && defaultUsed) {
Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized");
}
if (this.scriptExecutor == null) {
this.scriptExecutor = new DefaultScriptExecutor(this);
}
this.initialized = true;
}
如果不想使用默认的序列化器,可以自己指定序列化器或使用redis提供的StringRedisTemplate对象
5、配置序列化器
- 增加一个配置类,类上加@Configuration注解
- 添加如下方法,返回类型为RedisTemplate,并通过@Bean注解注入容器中
@Configuration
public class MyRedisConfig {
@Bean("myRedisTemplate")
public RedisTemplate myRedisTemplate(RedisConnectionFactory connectionFactory){
RedisTemplate myRedisTemplate = new RedisTemplate();
//设置连接工厂
myRedisTemplate.setConnectionFactory(connectionFactory);
//更换key和value的序列化器
myRedisTemplate.setKeySerializer(new StringRedisSerializer());
myRedisTemplate.setValueSerializer(new StringRedisSerializer());
return myRedisTemplate;
}
}
- 测试
@SpringBootTest
public class myRedisTemplateTest {
@Autowired
private RedisTemplate myRedisTemplate;
@Test
public void myRedisTemplateTest(){
Boolean flag = myRedisTemplate.opsForValue().setIfAbsent("name2", "zhangsan", 5 * 60, TimeUnit.SECONDS);
System.out.println("flag = " + flag);
String name2 = (String) myRedisTemplate.opsForValue().get("name2");
System.out.println("name2 = " + name2);
}
}
- redisTemlate加上序列化器后存储的数据
redisTemlate指定序列化器后存储的数据 |
---|
6、StringRedisTemplate
6.2 StringRedisTemplate分析
StringRedisTemplate就相当于指定了String序列化器的RedisTemplate对象。
查看org.springframework.data.redis.core包下的StringRedisTemplate源码:
public class StringRedisTemplate extends RedisTemplate<String, String> {
public StringRedisTemplate() {
this.setKeySerializer(RedisSerializer.string());
this.setValueSerializer(RedisSerializer.string());
this.setHashKeySerializer(RedisSerializer.string());
this.setHashValueSerializer(RedisSerializer.string());
}
public StringRedisTemplate(RedisConnectionFactory connectionFactory) {
this();
this.setConnectionFactory(connectionFactory);
this.afterPropertiesSet();
}
protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
return new DefaultStringRedisConnection(connection);
}
}
从源码中可以看到StringRedisTemplate构造函数中指定了key、value的序列化器为string序列化器
这就相当于第五点我们自定义RedisTemplate并指定string序列化器。因此我们可以直接注入使用StringRedisTemplate对象
6.2 StringRedisTemplate使用
@SpringBootTest
public class myRedisTemplateTest {
@Resource
private StringRedisTemplate stringRedisTemplate;
@Test
public void test(){
stringRedisTemplate.opsForValue().set("age","123");
}
}
StringRedisTemplate使用结果 |
---|
7、redisTemplate存储对象
使用redisTemplate的opsForValue可以存储对象,存储时会把对象转成字节数组来存储
@SpringBootTest
public class SaveObjectTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void saveTest(){
Person person = new Person();
person.setId(1);
person.setName("zhangsan");
person.setAge(20);
//使用redisTemplate的opsForValue可以存储对象,存储时会把对象转成字节数组来存储
redisTemplate.opsForValue().set("person"+person.getId(),person);
Person person1 = (Person) redisTemplate.opsForValue().get("person1");
System.out.println("person1 = " + person1);
}
}
相比较与jedis存储对象,更加方便,去掉了我们自己自定义的将对象转为字符串或者字符数组的过程。redisTemplate会将对象转为字节数组来存储。
运行结果:
redisTemplate存储对象 |
---|
8、redisTemplate管道操作
- 不使用管道存储10000个对象,用时约7158ms
@SpringBootTest
public class SaveObjectTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void saveTest(){
Person person = new Person();
person.setId(1);
person.setName("zhangsan");
person.setAge(20);
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
redisTemplate.opsForValue().set("person" + person.getId()+i, person);
}
System.out.println(System.currentTimeMillis()-start); //用时7158ms
}
}
- 使用管道存储10000个对象
@SpringBootTest
public class SaveObjectTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void pipelineTest() {
long start = System.currentTimeMillis();
redisTemplate.executePipelined(new SessionCallback<String>() {
@Override
public String execute(RedisOperations operations) throws DataAccessException {
Person person = new Person();
person.setId(1);
person.setName("zhangsan");
person.setAge(20);
long start = System.currentTimeMillis();
for (int i = 1; i < 10000; i++) {
operations.opsForValue().set("person" + i, "person:" + person);
}
System.out.println(System.currentTimeMillis()-start); //312ms
return null;
}
});
System.out.println(System.currentTimeMillis()-start);//2123ms
}
}
管道存储10000个对象,用时约2123ms |
---|