草庐IT

SpringBoot整合Redis--RedisTemplate

lzy-blogs 2023-03-28 原文

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

有关SpringBoot整合Redis--RedisTemplate的更多相关文章

  1. springboot定时任务 - 2

    如果您希望在Spring中启用定时任务功能,则需要在主类上添加 @EnableScheduling 注解。这样Spring才会扫描 @Scheduled 注解并执行定时任务。在大多数情况下,只需要在主类上添加 @EnableScheduling 注解即可,不需要在Service层或其他类中再次添加。以下是一个示例,演示如何在SpringBoot中启用定时任务功能:@SpringBootApplication@EnableSchedulingpublicclassApplication{publicstaticvoidmain(String[]args){SpringApplication.ru

  2. 基于SpringBoot的线上日志阅读器 - 2

    软件特点部署后能通过浏览器查看线上日志。支持Linux、Windows服务器。采用随机读取的方式,支持大文件的读取。支持实时打印新增的日志(类终端)。支持日志搜索。使用手册基本页面配置路径配置日志所在的目录,配置后按回车键生效,下拉框选择日志名称。选择日志后点击生效,即可加载日志。windows路径E:\java\project\log-view\logslinux路径/usr/local/XX历史模式历史模式下,不会读取新增的日志。针对历史文件可以分页读取,配置分页大小、跳转。历史模式下,支持根据关键词搜索。目前搜索引擎使用的是jdk自带类库,搜索速度相对较低,优点是比较简单。2G日志全文搜

  3. springboot使用validator进行参数校验 - 2

    1.依赖导入org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-validation2.validation常用注解@Null被注释的元素必须为null@NotNull被注释的元素不能为null,可以为空字符串@AssertTrue被注释的元素必须为true@AssertFalse被注释的元素必须为false@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值@D

  4. ruby - 如何将 Interactive Ruby 整合到我的开发过程中? - 2

    我正在尝试找到一种更好的方法将IRB与我的常规ruby​​开发集成。目前我很少在我的代码中使用IRB。我只用它来验证语法或尝试一些小的东西。我知道我可以将我自己的代码加载到ruby​​中作为一个require'mycode'但这通常不符合我的编程风格。有时我要检查的变量超出范围或在循环内。有没有一种简单的方法可以启动我的脚本并在IRB内的某个点卡住?我想我正在寻找一种更简单的方法来调试我的ruby​​代码而不破坏我的F5(编译)键。也许有经验的ruby开发者可以和我分享一个更精简的开发方法。 最佳答案 安装ruby​​-debugg

  5. ruby - 使用 Drupal 和 Ruby。有没有人整合两者? - 2

    我开始了一个小型网络项目并使用Drupal来构建它。到目前为止,还不错:您可以快速建立一个不错的面向CMS的网站,通过模块添加社交功能,并且您有一个广泛的API可以在一个架构良好的平台中进行自定义。现在问题来了:网站的增长超出了最初的计划,我发现自己正处于认真开始为它编写代码的境地。由于Drupal项目,我对PHP有了新的认识,但我想用Ruby来做。我会感觉更舒服,以后维护起来更容易,我可以在其他Ruby/Rails应用程序中重用它。随着时间的推移,我想我会用Ruby重写Drupal中的现有部分。基于此,问题是:是否有人将两者(成功或失败的故事)结合起来?这是一个相当大的决定,但我在G

  6. 停车系统源码-基于springboot+uniapp开源项目 - 2

    Iparking停车收费管理系统-可商用介绍Iparking是一款基于springBoot的停车收费管理系统,支持封闭车场和路边车场,支持微信支付宝多种支付渠道,支持多种硬件,涵盖了停车场管理系统的所有基础功能。技术栈Springboot,MybatisPlus,Beetl,Mysql,Redis,RabbitMQ,UniApp功能云端功能序号模块功能描述1系统管理菜单管理配置系统菜单2系统管理组织管理管理组织机构3系统管理角色管理配置系统角色,包含数据权限和功能权限配置4系统管理用户管理管理后台用户5系统管理租户管理多租户管理6系统管理公众号配置租户公众号配置7系统管理操作日志审计日志8系统

  7. 优化大数据量查询方案——SpringBoot(Cloud)整合ES - 2

    一、Elasticsearch简介实际业务场景中,多端的查询功能都有很大的优化空间。常见的处理方式有:建索引、建物化视图简化查询逻辑、DB层之上建立缓存、分页…然而随着业务数据量的不断增多,总有那么一张表或一个业务,是无法通过常规的处理方式来缩短查询时间的。在查询功能优化上,作为开发人员应该站在公司的角度,本着优化客户体验的目的去寻找解决方案。本人有幸做过Tomcat整合solr,今天一起研究一下当前比较火热的Elasticsearch搜索引擎。Elasticsearch是一个非常强大的搜索引擎。它目前被广泛地使用于各个IT公司。Elasticsearch是由Elastic公司创建。它的代码位

  8. SpringBoot+Netty实现TCP客户端实现接收数据按照16进制解析并存储到Mysql以及Netty断线重连检测与自动重连 - 2

    场景在SpringBoot项目中需要对接三方系统,对接协议是TCP,需实现一个TCP客户端接收服务端发送的数据并按照16进制进行解析数据,然后对数据进行过滤,将指定类型的数据通过mybatis存储进mysql数据库中。并且当tcp服务端断连时,tcp客户端能定时检测并发起重连。全流程效果 注:博客:霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主实现1、SpringBoot+Netty实现TCP客户端本篇参考如下博客,在如下博客基础上进行修改Springboot+Netty搭建基于TCP协议的客户端(二):https://www.cnblogs.com/haolb

  9. Java面试--SpringBoot启动流程 - 2

    一、SpringBoot是什么SpringBoot是依赖于Spring的,比起Spring,除了拥有Spring的全部功能以外,SpringBoot无需繁琐的Xml配置,这取决于它自身强大的自动装配功能;并且自身已嵌入Tomcat、Jetty等web容器,集成了SpringMvc,使得SpringBoot可以直接运行,不需要额外的容器,提供了一些大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等,其实Spring大家都知道,Boot是启动的意思。所以,SpringBoot其实就是一个启动Spring项目的一个工具而已,总而言之,SpringBoot是一个服务于框架的

  10. springboot Socket 通信 - 2

    一、引入依赖:dependency>groupId>org.springframework.bootgroupId>artifactId>spring-boot-starter-websocketartifactId>2.7.1-->dependency>二、准备工具类:/***@authorWeiDaPang*/@ConfigurationpublicclassScheduledConfiguration{@BeanpublicTaskSchedulertaskScheduler(){ThreadPoolTaskSchedulertaskScheduler=newThreadPoolTask

随机推荐