Jedis,SpringDataRedis

快速入门

导入依赖

XML 复制代码
        <!--jedis-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.7.0</version>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.7.0</version>
            <scope>test</scope>
        </dependency>

测试代码

java 复制代码
package com.example;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;

public class JedisTest {
    private Jedis jedis;

    @BeforeEach
    void setUp() {
        jedis = new Jedis("192.168.168.168", 6379);
        jedis.auth("123456");
        jedis.select(0);
    }

    @Test
    void test() {
        String name = jedis.get("name");
        System.out.println(name);
    }

    @AfterEach
    void tearDown() {
        if(jedis != null){
            jedis.close();
        }
    }
}

jedis连接池

Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此推荐大家使用Jedis连接池代替Jedis的直连方式。

java 复制代码
package com.example.utils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisConnectionFactory {
    private static JedisPool jedisPool;
    //在类加载时执行
    static {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(8);//最大连接数
        poolConfig.setMaxIdle(8);//最大空闲连接数
        poolConfig.setMinIdle(0);//最小空闲连接数
        poolConfig.setMaxWaitMillis(1000);//最大等待时间 (单位:毫秒)
        jedisPool = new JedisPool(poolConfig, "192.168.168.168", 6379, 1000, "123456");
    }//连接超时时间 1000毫秒
    public static Jedis getJedis() {
        return jedisPool.getResource();
    }
}

修改后这样获取jedis对象

java 复制代码
    @BeforeEach
    void setUp() {
        jedis = JedisConnectionFactory.getJedis();
        jedis.auth("123456");
        jedis.select(0);
    }

SpringDataRedis

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis,官网地址:Spring Data Redis

**- 提供了对不同Redis客户端的整合(Lettuce和Jedis)

  • 提供了RedisTemplate统一API来操作Redis
  • 支持Redis的发布订阅模型
  • 支持Redis哨兵和Redis集群
  • 支持基于Lettuce的响应式编程
  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
  • 支持基于Redis的JDKCollection实现**

快速入门

导入依赖

XML 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

配置redis

XML 复制代码
spring:
  data:
    redis:
      host: 192.168.168.168
      port: 6379
      password: 123456
      database: 0
      lettuce:
        pool:
          max-active: 8
          max-idle: 8
          min-idle: 0
          max-wait: 100ms

测试

java 复制代码
package com.example;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
public class RedisTemplateTest {
    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void test01() {
        redisTemplate.opsForValue().set("name","lihua");
        System.out.println(redisTemplate.opsForValue().get("name"));
    }
}

自定义序列化

jdk序列化(默认的序列化方式)的问题

进行如上测试后,发现并没有修改key为name的值为lihua,而是出现了这样的结果

原因如下

RedisTemplate可以接收任意Object作为值写入Redis:

只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:

缺点:
**- 可读性差

  • 内存占用较大**

***************************************************

自定义序列化方式为json序列化

首先写一个RedisTemplate的配置

java 复制代码
package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

@Configuration
public class RedisTemplateConfig {
    @Bean
    //RedisConnectionFactory是spring内置的,在项目启动时会自动装配,因此作为参数传入即可
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        //创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //设置连接工厂
        template.setConnectionFactory(factory);
        //创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        //设置key的序列化   RedisSerializer是redis的一个序列化器
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        //设置value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        //返回
        return template;
    }
}

在springboot项目启动时,这个bean就会被加载

重新测试

java 复制代码
    @Test
    public void test01() {
        redisTemplate.opsForValue().set("name","zhaosi");
        System.out.println(redisTemplate.opsForValue().get("name"));
    }

测试结果如下

符合我们的预期

*********************************

也可以存入自定义对象

java 复制代码
    @Test
    public void test02() {
        User u1 = new User(1, "laoda", 24);
        redisTemplate.opsForValue().set("user:001", u1);
    }
    @Test
    public void test03() {
        User user = (User) redisTemplate.opsForValue().get("user:001");
        System.out.println(user);
    }

测试结果如下

**整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。**不过,其中记录了序列化时对应的class名称,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。 (我们将用StringRedisTemplate进行改进)

SpringRedisTemplate

为了节省内存空间,我们可以不使用JSON序列化器来处理value,而是统一使用String序列化器(这样value就不用存储对象的字节码文件了),要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。

因为存入和读取时的序列化及反序列化都是我们自己实现的,SpringDataRedis就不会将class信息写入Redis了。

这种用法比较普遍,因此SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate,它的key和value的序列化方式默认就是String方式。

导入jackson依赖

XML 复制代码
        <!--Jackson依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>

省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用就好了

java 复制代码
@SpringBootTest
public class StringRedisTemplateTest {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static final ObjectMapper mapper = new ObjectMapper();

    @Test
    public void test() throws JsonProcessingException {
        User u1 = new User(2, "赵四", 25);
        //手动序列化
        String json = mapper.writeValueAsString(u1);
        System.out.println("序列化后的json字符串:"+json);
        //写入数据
        stringRedisTemplate.opsForValue().set("user:002",json);
        //获取数据
        String jsonUser = stringRedisTemplate.opsForValue().get("user:002");
        //反序列化
        User user = mapper.readValue(jsonUser, User.class);
        System.out.println("反序列化得到的结果:"+user);
    }
}

可以看到,里面是没有对象的字节码的

相关推荐
api771 小时前
1688商品详情API返回值中的售后保障与服务信息
java·服务器·前端·javascript·python·spring·pygame
赵广陆1 小时前
SprinBoot+Vue门诊管理系统的设计与实现
前端·javascript·vue.js·spring boot·maven
华山令狐虫2 小时前
el-tabs 样式修改
前端
史努比的大头4 小时前
前端开发深入了解webpack
前端
Dovir多多4 小时前
渗透测试入门学习——php与mysql数据库连接、使用session完成简单的用户注册、登录
前端·数据库·后端·mysql·安全·html·php
B.-4 小时前
Remix 学习 - @remix-run/react 中主要的 hooks
前端·javascript·学习·react.js·web
小刘|4 小时前
《实现 HTML 图片轮播效果》
前端·html
罗_三金5 小时前
微信小程序读写NFC标签(实现NFC标签快速拉起小程序)实战
前端·javascript·微信小程序·小程序
大大。5 小时前
el-input 只能输入数字和一个小数点,或者只能输入正整数
前端·javascript·vue.js
盼盼盼6 小时前
如何避免在使用 Context API 时出现状态管理的常见问题?
前端·javascript·react.js