SpringBoot整合Redis--RedisTemplate

打印 上一主题 下一主题

主题 844|帖子 844|积分 2532

SpringBoot整合Redis--RedisTemplate

1、导入依赖
  1. <dependency>
  2.     <groupId>org.springframework.boot</groupId>
  3.     <artifactId>spring-boot-starter-data-redis</artifactId>
  4. </dependency>
复制代码
2、编写配置文件
  1. spring:
  2.   redis:
  3.     host: 192.168.27.132
  4.     port: 6379
  5.     password: lzyredis
  6.     database: 1
  7.     jedis:
  8.       pool:
  9.         max-active: 10
  10.         max-wait: 3000
  11.         min-idle: 5
  12.         max-idle: 10
复制代码
3、测试代码

RedisTemplate.opsForXxx().操作

  • Xxx:代表要操作的数据类型【value代表操作的是string】
  1. @SpringBootTest
  2. class SpringbootRedisDemoApplicationTests {
  3.     @Autowired
  4.     private RedisTemplate redisTemplate;
  5.     @Test
  6.     public void test(){
  7.         //setIfAbsent 就是 setnx
  8.         Boolean absent = redisTemplate.opsForValue().setIfAbsent("name", "xiaoming", 5 * 60, SECONDS);
  9.         System.out.println("absent = " + absent);
  10.         String name = (String) redisTemplate.opsForValue().get("name");
  11.         System.out.println("name = " + name);
  12.     }
  13. }
复制代码
springboot整合redis测试后存储的数据打印结果在第一张图中发现存储的key和value前出现了一些不认识的字符,虽然在RedisDesktopManager工具上显示不是期望的格式,但在打印结果上看却是正常显示的。
这是因为使用RedisTemplate来操作字符串时,在存储数据时会对key和value进行序列化操作。
序列化操作会对选择对应的序列化器来操作,如果没有指定序列化器,那么默认选择是JDK序列化器
所以会出现一长串字符串。
4、RedisTemplate选择序列化器的原理:

RedisTemplate 继承RedisAccessor类,而该类实现了InitializingBean接口,
所以RedisTemplate会调用afterPropertiesSet方法。
在该方法中会对操作key和value进行序列化操作,
如果指定了具体的序列化器,那么就会使用指定的序列化器,
如果没有指定具体的序列化器,则使用JDK序列化器
  1. public void afterPropertiesSet() {
  2.     super.afterPropertiesSet();
  3.     boolean defaultUsed = false;
  4.     if (this.defaultSerializer == null) {
  5.         //没有指定的序列化器,那默认序列化器就为jdk序列化器
  6.         this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());
  7.     }
  8.     if (this.enableDefaultSerializer) {
  9.         if (this.keySerializer == null) {
  10.             this.keySerializer = this.defaultSerializer;
  11.             defaultUsed = true;
  12.         }
  13.         if (this.valueSerializer == null) {
  14.             this.valueSerializer = this.defaultSerializer;
  15.             defaultUsed = true;
  16.         }
  17.         if (this.hashKeySerializer == null) {
  18.             this.hashKeySerializer = this.defaultSerializer;
  19.             defaultUsed = true;
  20.         }
  21.         if (this.hashValueSerializer == null) {
  22.             this.hashValueSerializer = this.defaultSerializer;
  23.             defaultUsed = true;
  24.         }
  25.     }
  26.     if (this.enableDefaultSerializer && defaultUsed) {
  27.         Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized");
  28.     }
  29.     if (this.scriptExecutor == null) {
  30.         this.scriptExecutor = new DefaultScriptExecutor(this);
  31.     }
  32.     this.initialized = true;
  33. }
复制代码
如果不想使用默认的序列化器,可以自己指定序列化器或使用redis提供的StringRedisTemplate对象
5、配置序列化器


  • 增加一个配置类,类上加@Configuration注解
  • 添加如下方法,返回类型为RedisTemplate,并通过@Bean注解注入容器中
  1. @Configuration
  2. public class MyRedisConfig {
  3.     @Bean("myRedisTemplate")
  4.     public RedisTemplate myRedisTemplate(RedisConnectionFactory connectionFactory){
  5.         RedisTemplate myRedisTemplate = new RedisTemplate();
  6.         //设置连接工厂
  7.         myRedisTemplate.setConnectionFactory(connectionFactory);
  8.         //更换key和value的序列化器
  9.         myRedisTemplate.setKeySerializer(new StringRedisSerializer());
  10.         myRedisTemplate.setValueSerializer(new StringRedisSerializer());
  11.         return myRedisTemplate;
  12.     }
  13. }
复制代码

  • 测试
  1. @SpringBootTest
  2. public class myRedisTemplateTest {
  3.     @Autowired
  4.     private RedisTemplate myRedisTemplate;
  5.     @Test
  6.     public void myRedisTemplateTest(){
  7.         Boolean flag = myRedisTemplate.opsForValue().setIfAbsent("name2", "zhangsan", 5 * 60, TimeUnit.SECONDS);
  8.         System.out.println("flag = " + flag);
  9.         String  name2 = (String) myRedisTemplate.opsForValue().get("name2");
  10.         System.out.println("name2 = " + name2);
  11.     }
  12. }
复制代码

  • redisTemlate加上序列化器后存储的数据
redisTemlate指定序列化器后存储的数据6、StringRedisTemplate

6.2 StringRedisTemplate分析

StringRedisTemplate就相当于指定了String序列化器的RedisTemplate对象
查看org.springframework.data.redis.core包下的StringRedisTemplate源码:
  1. public class StringRedisTemplate extends RedisTemplate<String, String> {
  2.     public StringRedisTemplate() {
  3.         this.setKeySerializer(RedisSerializer.string());
  4.         this.setValueSerializer(RedisSerializer.string());
  5.         this.setHashKeySerializer(RedisSerializer.string());
  6.         this.setHashValueSerializer(RedisSerializer.string());
  7.     }
  8.     public StringRedisTemplate(RedisConnectionFactory connectionFactory) {
  9.         this();
  10.         this.setConnectionFactory(connectionFactory);
  11.         this.afterPropertiesSet();
  12.     }
  13.     protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
  14.         return new DefaultStringRedisConnection(connection);
  15.     }
  16. }
复制代码
从源码中可以看到StringRedisTemplate构造函数中指定了key、value的序列化器为string序列化器
这就相当于第五点我们自定义RedisTemplate并指定string序列化器。因此我们可以直接注入使用StringRedisTemplate对象
6.2 StringRedisTemplate使用
  1. @SpringBootTest
  2. public class myRedisTemplateTest {
  3.     @Resource
  4.     private StringRedisTemplate stringRedisTemplate;
  5.     @Test
  6.     public void test(){
  7.         stringRedisTemplate.opsForValue().set("age","123");
  8.     }
  9. }
复制代码
StringRedisTemplate使用结果7、redisTemplate存储对象

使用redisTemplate的opsForValue可以存储对象,存储时会把对象转成字节数组来存储
  1. @SpringBootTest
  2. public class SaveObjectTest {
  3.     @Autowired
  4.     private RedisTemplate redisTemplate;
  5.     @Test
  6.     public void saveTest(){
  7.         Person person = new Person();
  8.         person.setId(1);
  9.         person.setName("zhangsan");
  10.         person.setAge(20);
  11.                 //使用redisTemplate的opsForValue可以存储对象,存储时会把对象转成字节数组来存储
  12.         redisTemplate.opsForValue().set("person"+person.getId(),person);
  13.         Person person1 = (Person) redisTemplate.opsForValue().get("person1");
  14.         System.out.println("person1 = " + person1);
  15.     }
  16. }
复制代码
相比较与jedis存储对象,更加方便,去掉了我们自己自定义的将对象转为字符串或者字符数组的过程。redisTemplate会将对象转为字节数组来存储。
运行结果:
redisTemplate存储对象8、redisTemplate管道操作


  • 不使用管道存储10000个对象,用时约7158ms
  1. @SpringBootTest
  2. public class SaveObjectTest {
  3.     @Autowired
  4.     private RedisTemplate redisTemplate;
  5.     @Test
  6.     public void saveTest(){
  7.         Person person = new Person();
  8.         person.setId(1);
  9.         person.setName("zhangsan");
  10.         person.setAge(20);
  11.         long start = System.currentTimeMillis();
  12.         for (int i = 0; i < 10000; i++) {
  13.             redisTemplate.opsForValue().set("person" + person.getId()+i, person);
  14.         }
  15.         System.out.println(System.currentTimeMillis()-start); //用时7158ms
  16.     }
  17. }
复制代码

  • 使用管道存储10000个对象
  1. @SpringBootTest
  2. public class SaveObjectTest {
  3.     @Autowired
  4.     private RedisTemplate redisTemplate;
  5.    @Test
  6.     public void pipelineTest() {
  7.         long start = System.currentTimeMillis();
  8.         redisTemplate.executePipelined(new SessionCallback<String>() {
  9.             @Override
  10.             public String execute(RedisOperations operations) throws DataAccessException                         {
  11.                 Person person = new Person();
  12.                 person.setId(1);
  13.                 person.setName("zhangsan");
  14.                 person.setAge(20);
  15.                 long start = System.currentTimeMillis();
  16.                 for (int i = 1; i < 10000; i++) {
  17.                     operations.opsForValue().set("person" + i, "person:" + person);
  18.                 }
  19.                 System.out.println(System.currentTimeMillis()-start); //312ms
  20.                 return null;
  21.             }
  22.         });
  23.         System.out.println(System.currentTimeMillis()-start);//2123ms
  24.     }
  25. }
复制代码
管道存储10000个对象,用时约2123ms
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

前进之路

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表