SpringBoot整合Redis-

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测试后存储的数据
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
hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » SpringBoot整合Redis-