ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

SpringBoot整合Redis--RedisTemplate

2022-06-24 19:35:52  阅读:142  来源: 互联网

标签:SpringBoot -- Redis System person redisTemplate 序列化 public RedisTemplate


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测试后存储的数据
image
打印结果
image

在第一张图中发现存储的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指定序列化器后存储的数据
image

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使用结果
image

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存储对象
image

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
image

标签:SpringBoot,--,Redis,System,person,redisTemplate,序列化,public,RedisTemplate
来源: https://www.cnblogs.com/lzy-blogs/p/16409979.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有