Bootstrap

springboot整合redis 复制即用

Redis的Java客户端

  • 目前主流的Redis的Java客户端有三种
    • Jedis和Lettuce:这两个主要是提供了Redis命令对应的API,方便我们操作Redis,而SpringDataRedis又对这两种做了抽象和封装,因此我们后期会直接以SpringDataRedis来学习。
    • Redisson:是在Redis基础上实现了分布式的可伸缩的java数据结构,例如Map、Queue等,而且支持跨进程的同步机制:Lock、Semaphore等待,比较适合用来实现特殊的功能需求。

Jedis客户端

快速入门
  • 使用Jedis的步骤

    1. 导入Jedis的maven坐标
    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>
    
    1. 建立连接
      新建一个单元测试类
    JAVA
    
    private Jedis jedis;
    
    @BeforeEach
    void setUp() {
        //1. 建立连接
        jedis = new Jedis("101.42.225.160", 6379);
        //2. 设置密码
        jedis.auth("root");
        //3. 选择库
        jedis.select(0);
    }
    
    1. 测试
    JAVA
    
    @Test
    void testString(){
        jedis.set("name","Kyle");
        String name = jedis.get("name");
        System.out.println("name = " + name);
    }
    
    @Test
    void testHash(){
        jedis.hset("reggie:user:1","name","Jack");
        jedis.hset("reggie:user:2","name","Rose");
        jedis.hset("reggie:user:1","age","21");
        jedis.hset("reggie:user:2","age","18");
        Map<String, String> map = jedis.hgetAll("reggie:user:1");
        System.out.println(map);
    }
    
    1. 释放资源
    JAVA
    @AfterEach
    void tearDown(){
        if (jedis != null){
            jedis.close();
        }
    }
    
连接池
  • Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此我们推荐大家使用Jedis连接池代替Jedis的直连方式。
  • 新建一个com.blog.util,用于存放我们编写的工具类
  • 但后面我们使用SpringDataRedis的时候,可以直接在yml配置文件里配置这些内容
JAVA

public class JedisConnectionFactory {

    private static JedisPool jedisPool;

    static {
        // 配置连接池
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(8);
        poolConfig.setMaxIdle(8);
        poolConfig.setMinIdle(0);
        poolConfig.setMaxWaitMillis(1000);
        // 创建连接池对象,参数:连接池配置、服务端ip、服务端端口、超时时间、密码
        jedisPool = new JedisPool(poolConfig, "101.42.225.160", 6379, 1000, "root");
    }

    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
}
  • 之后我们的测试类就可以修改为如下
JAVA

@SpringBootTest
class RedisTestApplicationTests {

    private Jedis jedis = JedisConnectionFactory.getJedis();

    @Test
    void testString(){
        jedis.set("name","Kyle");
        String name = jedis.get("name");
        System.out.println("name = " + name);
    }

    @Test
    void testHash(){
        jedis.hset("reggie:user:1","name","Jack");
        jedis.hset("reggie:user:2","name","Rose");
        jedis.hset("reggie:user:3","name","Kyle");
        jedis.hset("reggie:user:1","age","21");
        jedis.hset("reggie:user:2","age","18");
        jedis.hset("reggie:user:3","age","18");
        Map<String, String> map = jedis.hgetAll("reggie:user:1");
        System.out.println(map);
    }

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

SpringDataRedis客户端(重点)

  • SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis
  • 官网地址:https://spring.io/projects/spring-data-redis
    • 提供了对不同Redis客户端的整合(Lettuce和Jedis)
    • 提供了RedisTemplate统一API来操作Redis
    • 支持Redis的发布订阅模型
    • 支持Redis哨兵和Redis集群
    • 支持基于Lettuce的响应式编程
    • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
    • 支持基于Redis的JDKCollection实现
  • SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:
API返回值类型说明
redisTemplate.opsForValue()ValueOperations操作String类型数据
redisTemplate.opsForHash()HashOperations操作Hash类型数据
redisTemplate.opsForList()ListOperations操作List类型数据
redisTemplate.opsForSet()SetOperations操作Set类型数据
redisTemplate.opsForzSet()ZSetOperations操作SortedSet类型数据
redisTemplate通用的命令
快速入门

SpringBoot已经提供了对SpringDataRedis的支持,使用起来非常简单

  1. 导入依赖,
XML

<!--redis依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--common-pool-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
<!--Jackson依赖-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
  1. 配置Redis
YML

spring:
  redis:
    host: 127.0.0.1    
    port: 6379
    password: root   需要改成自己的密码
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: 100ms
  1. 自定义序列化
  • RedisTemplate可以接收任意Object作为值写入Redis
  • 只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的

\xAC\xED\x00\x05t\x00\x06\xE5\xBC\xA0\xE4\xB8\x89

  • 缺点:
    • 可读性差
    • 内存占用较大
  • 我们可以自定义RedisTemplate的序列化方式,代码如下:
JAVA
@Configuration
public class redisConfig {

    /**
     * 创建并配置RedisTemplate,用于操作Redis数据库。
     * 
     * @param factory Redis连接工厂,用于创建Redis连接。
     * @return 配置好的RedisTemplate对象,可以用于执行Redis操作。
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();

        // 设置连接工厂
        template.setConnectionFactory(factory);
        // 设置键的序列化方式为字符串序列化
        template.setKeySerializer(new StringRedisSerializer());
        // 设置哈希键的序列化方式为字符串序列化
        template.setHashKeySerializer(new StringRedisSerializer());

        // 设置哈希值和值的序列化方式为JSON序列化
        template.setHashValueSerializer(serializer());
        template.setValueSerializer(serializer());

        return template;
    }

    /**
     * 创建并配置JSON序列化器。
     * 
     * @return 配置好的Jackson2JsonRedisSerializer对象,用于将对象序列化为JSON格式。
     */
    public Jackson2JsonRedisSerializer<Object> serializer() {
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper object = new ObjectMapper();
        // 启用对未知类型的默认推断
        object.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        // 设置在反序列化时,对于未知的属性不抛出异常
        object.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        object.registerModule(new JavaTimeModule());
        // 设置所有属性可见
        object.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 配置ObjectMapper到序列化器
        serializer.setObjectMapper(object);
        return serializer;
    }
}



  1. 注入RedisTemplate
    因为有了SpringBoot的自动装配,我们可以拿来就用
JAVA
@Autowired
private RedisTemplate redisTemplate;
  1. 编写测试方法
JAVA
@Test
void stringTest(){
    redisTemplate.opsForValue().set("username","David");
    String username = (String) redisTemplate.opsForValue().get("username");
    System.out.println(username);
}
  • 我们编写一个User类,并尝试将其创建的对象存入Redis,看看是什么效果
JAVA
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private Integer age;
}
  • 测试
JAVA
@Test
void stringTest(){
    redisTemplate.opsForValue().set("userdata",new User("张三",18));
}
  • 这里采用了JSON序列化来代替默认的JDK序列化方式。最终结果如下:
JSON
{
"com.kab.entity.User",
  "name": "张三",
  "age": 18
}
  • 整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。不过,其中记录了序列化时对应的class名称,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。
;