<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
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
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序列化器。
所以会出现一长串字符串。
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对象
@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指定序列化器后存储的数据 |
---|
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对象
@SpringBootTest public class myRedisTemplateTest { @Resource private StringRedisTemplate stringRedisTemplate; @Test public void test(){ stringRedisTemplate.opsForValue().set("age","123"); } }
StringRedisTemplate使用结果 |
---|
使用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存储对象 |
---|
@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 } }
@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 |
---|