RedisTemplate集成+封装RedisUtil过程

 更新时间:2024年12月09日 11:20:35   作者:S-X-S  
本文介绍了如何搭建一个多模块的Redis项目,包括项目搭建、配置和测试,通过使用父项目管理多个子模块,可以实现单点构建、统一版本管理和清晰的项目结构,文章还提供了在Spring Boot项目中集成RedisTemplate的示例,并解决了编码问题

1.项目搭建

创建一个redis模块

调整pom.xml,使其成为单独的模块

  • sun-common-redis的pom.xml 取消parent

  • sun-common的pom.xml 取消对redis模块的管理

  • sun-frame的pom.xml 增加对redis模块的管理

关于只在modules中配置子模块,但是子模块没有配置parent的用处

1. 多模块项目的构建管理

使用标签可以将多个子模块组织在一个顶层的父项目中,从而实现以下几个目标:

  • a. 单点构建
  • 你可以在父项目的根目录下运行一次mvn install命令,就可以构建和安装所有子模块到本地Maven仓库,而不需要分别进入每个子模块目录单独运行构建命令。这大大简化了多模块项目的构建过程。
  • b. 构建顺序管理
  • Maven会根据模块间的依赖关系,自动确定各个模块的构建顺序,确保在构建一个模块之前,先构建它所依赖的模块。这在多模块项目中是非常有用的,可以避免手动管理依赖顺序的麻烦。

2. 统一的版本管理

即使子模块没有指定父项目,使用标签仍然可以帮助你管理各个子模块的版本一致性。你可以在父项目的POM文件中统一指定各个子模块的版本号,然后在每个子模块的POM文件中引用这个版本号。

3. 项目结构的组织和清晰度

将多个子模块组织在一个父项目中,可以使项目结构更加清晰,便于管理。通过标签,你可以一目了然地看到项目中包含哪些子模块,以及它们之间的组织结构。

sun-common-redis引入redis依赖

    <dependencies>
        <!-- redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.4.2</version>
        </dependency>
        <!-- redis的pool -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.9.0</version>
        </dependency>
    </dependencies>

2.sun-user集成RedisTemplate

pom.xml引入sun-common-redis

        <!-- 引入sun-common-redis -->
        <dependency>
            <groupId>com.sunxiansheng</groupId>
            <artifactId>sun-common-redis</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

application.yml配置redis(集群模式)

spring:
  #  配置redis(集群模式)
  redis:
    password: # Redis服务器密码
    database: 0 # 默认数据库为0号
    timeout: 10000ms # 连接超时时间是10000毫秒
    lettuce:
      pool:
        max-active: 8 # 最大活跃连接数,使用负值表示没有限制,最佳配置为核数*2
        max-wait: 10000ms # 最大等待时间,单位为毫秒,使用负值表示没有限制,这里设置为10秒
        max-idle: 200 # 最大空闲连接数
        min-idle: 5 # 最小空闲连接数
    cluster:
      nodes:
  

TestController.java测试RedisTemplate

代码

package com.sunxiansheng.user.controller;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * Description:
 * @Author sun
 * @Create 2024/7/8 17:55
 * @Version 1.0
 */
@RestController
public class TestController {

    @Resource
    private RedisTemplate redisTemplate;

    @RequestMapping("/testRedis")
    public String testRedis() {
        redisTemplate.opsForValue().set("name", "sunxiansheng");
        return "Hello World!";
    }
}

访问测试(发现有乱码)

重写RedisTemlate

引入Jackson的依赖

        <!-- 重写RedisTemlate需要的jackson序列化工具 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.8.5</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.11.4</version>
        </dependency>

RedisConfig.java

package com.sunxiansheng.redis.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * Description: RedisConfig配置类
 * @Author sun
 * @Create 2024/7/19 11:11
 * @Version 1.0
 */
@Configuration
public class RedisConfig {

    /**
     * 重写RedisTemplate 解决乱码问题
     *
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // key就使用redis提供的序列化RedisSerializer即可
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(redisSerializer);
        redisTemplate.setHashKeySerializer(redisSerializer);
        // value要使用Jackson的序列化
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer());
        return redisTemplate;
    }

    /**
     * 获取一个Jackson的序列化对象逻辑
     *
     * @return
     */
    private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
        // 创建一个Jackson2JsonRedisSerializer对象,用于序列化和反序列化Java对象
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        // 创建一个ObjectMapper对象,用于JSON序列化和反序列化的配置
        ObjectMapper objectMapper = new ObjectMapper();
        // 设置ObjectMapper的可见性,使其可以访问所有属性
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 配置ObjectMapper,使其在遇到未知属性时不会抛出异常
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 将配置好的ObjectMapper设置到Jackson2JsonRedisSerializer中
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        // 返回配置好的Jackson2JsonRedisSerializer对象
        return jackson2JsonRedisSerializer;
    }

}

测试

3.封装RedisUtil

RedisUtil.java

package com.sunxiansheng.redis.util;

import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Description: RedisUtil工具类
 * @Author sun
 * @Create 2024/6/5 14:17
 * @Version 1.0
 */
@Component
public class RedisUtil {

    @Resource
    private RedisTemplate redisTemplate;

    private static final String CACHE_KEY_SEPARATOR = ".";

    /**
     * 构建缓存key
     * @param strObjs 多个字符串拼接成缓存key
     * @return 拼接后的缓存key
     */
    public String buildKey(String... strObjs) {
        return Stream.of(strObjs).collect(Collectors.joining(CACHE_KEY_SEPARATOR));
    }

    /**
     * 是否存在key
     * @param key Redis中的key
     * @return true如果key存在,否则false
     */
    public boolean exist(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 删除key
     * @param key Redis中的key
     * @return true如果删除成功,否则false
     */
    public boolean del(String key) {
        return redisTemplate.delete(key);
    }

    /**
     * 设置key-value对
     * @param key Redis中的key
     * @param value 要设置的值
     */
    public void set(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 设置key-value对,如果key不存在,则设置成功,并指定过期时间
     * @param key Redis中的key
     * @param value 要设置的值
     * @param time 过期时间
     * @param timeUnit 时间单位
     * @return true如果设置成功,否则false
     */
    public boolean setNx(String key, String value, Long time, TimeUnit timeUnit) {
        return redisTemplate.opsForValue().setIfAbsent(key, value, time, timeUnit);
    }

    /**
     * 获取指定key的值
     * @param key Redis中的key
     * @return key对应的值
     */
    public String get(String key) {
        return (String) redisTemplate.opsForValue().get(key);
    }

    /**
     * 向有序集合中添加元素
     * @param key Redis中的key
     * @param value 元素的值
     * @param score 元素的分数
     * @return true如果添加成功,否则false
     */
    public Boolean zAdd(String key, String value, Long score) {
        return redisTemplate.opsForZSet().add(key, value, Double.valueOf(String.valueOf(score)));
    }

    /**
     * 获取有序集合的元素数量
     * @param key Redis中的key
     * @return 元素数量
     */
    public Long countZset(String key) {
        return redisTemplate.opsForZSet().size(key);
    }

    /**
     * 获取有序集合指定范围内的元素
     * @param key Redis中的key
     * @param start 起始位置
     * @param end 结束位置
     * @return 指定范围内的元素集合
     */
    public Set<String> rangeZset(String key, long start, long end) {
        return redisTemplate.opsForZSet().range(key, start, end);
    }

    /**
     * 删除有序集合中的指定元素
     * @param key Redis中的key
     * @param value 要删除的元素
     * @return 被删除的元素数量
     */
    public Long removeZset(String key, Object value) {
        return redisTemplate.opsForZSet().remove(key, value);
    }

    /**
     * 删除有序集合中的多个元素
     * @param key Redis中的key
     * @param value 要删除的元素集合
     */
    public void removeZsetList(String key, Set<String> value) {
        value.forEach(val -> redisTemplate.opsForZSet().remove(key, val));
    }

    /**
     * 获取有序集合中指定元素的分数
     * @param key Redis中的key
     * @param value 元素的值
     * @return 元素的分数
     */
    public Double score(String key, Object value) {
        return redisTemplate.opsForZSet().score(key, value);
    }

    /**
     * 获取有序集合中指定分数范围内的元素
     * @param key Redis中的key
     * @param start 起始分数
     * @param end 结束分数
     * @return 指定分数范围内的元素集合
     */
    public Set<String> rangeByScore(String key, long start, long end) {
        return redisTemplate.opsForZSet().rangeByScore(key, Double.valueOf(String.valueOf(start)), Double.valueOf(String.valueOf(end)));
    }

    /**
     * 增加有序集合中指定元素的分数
     * @param key Redis中的key
     * @param obj 元素的值
     * @param score 增加的分数
     * @return 增加后的分数
     */
    public Object addScore(String key, Object obj, double score) {
        return redisTemplate.opsForZSet().incrementScore(key, obj, score);
    }

    /**
     * 获取有序集合中指定元素的排名
     * @param key Redis中的key
     * @param obj 元素的值
     * @return 元素的排名
     */
    public Object rank(String key, Object obj) {
        return redisTemplate.opsForZSet().rank(key, obj);
    }

    /**
     * 从 Redis 有序集合(Sorted Set)中按分数范围获取成员及其分数
     * @param key 排行榜的key
     * @param start 起始位置(包含)
     * @param end 结束位置(包含)
     * @return Set<ZSetOperations.TypedTuple<String>> : 每个 TypedTuple 对象包含以下内容:value: 集合中的成员,score: 成员的分数。
     */
    public Set<ZSetOperations.TypedTuple<String>> rankWithScore(String key, long start, long end) {
        return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);
    }

    /**
     * 向Redis中的hash结构存储数据
     * @param key 一个hash结构的key
     * @param hashKey hash中的小key
     * @param hashVal hash中的小value
     */
    public void putHash(String key, String hashKey, Object hashVal) {
        redisTemplate.opsForHash().put(key, hashKey, hashVal);
    }

    /**
     * Redis中的String类型,获取value时将其转换为int类型
     * @param key Redis中的key
     * @return key对应的整数值
     */
    public Integer getInt(String key) {
        return (Integer) redisTemplate.opsForValue().get(key);
    }

    /**
     * Redis中的String类型,将value增加一
     * @param key Redis中的key
     * @param count 增加的数量
     */
    public void increment(String key, Integer count) {
        redisTemplate.opsForValue().increment(key, count);
    }

    /**
     * Redis中的hash类型,根据key来将每一个hashKey和hashValue转换为Map类型
     * @param key Redis中的hash结构的key
     * @return Map<Object, Object> 包含hash结构中的所有键值对
     */
    public Map<Object, Object> getHashAndDelete(String key) {
        Map<Object, Object> map = new HashMap<>();
        // 扫描hash,指定每一个Entry的类型,这里返回的就是Map的游标,可以进行遍历
        Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(key, ScanOptions.NONE);
        // 遍历每一条数据,放到map中
        while (cursor.hasNext()) {
            Map.Entry<Object, Object> next = cursor.next();
            Object hashKey = next.getKey();
            Object hashValue = next.getValue();
            map.put(hashKey, hashValue);
            // 每遍历一条就删除
            redisTemplate.opsForHash().delete(key, hashKey);
        }
        return map;
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Redis精确去重计数方法(咆哮位图)

    Redis精确去重计数方法(咆哮位图)

    这篇文章主要给大家介绍了关于Redis精确去重计数方法(咆哮位图)的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Redis具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • 使用注解实现Redis缓存功能

    使用注解实现Redis缓存功能

    这篇文章主要为大家详细介绍了使用注解实现Redis缓存功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • redis中的事务操作案例分析

    redis中的事务操作案例分析

    这篇文章主要介绍了redis中的事务操作案例,结合具体实例形式详细分析了redis事务操作的概念、原理、使用技巧与相关注意事项,需要的朋友可以参考下
    2019-07-07
  • 详解Redis中的简单动态字符串和C字符串的区别

    详解Redis中的简单动态字符串和C字符串的区别

    简单动态字符串(SDS)和 C 字符串在实现和特性上存在一些区别,这些区别使得 SDS 更适合作为 Redis 中字符串对象的内部表示,本文给大家介绍一下Redis中的简单动态字符串和C字符串的区别,需要的朋友可以参考下
    2023-12-12
  • Windows下注册Redis服务失败的解决方案

    Windows下注册Redis服务失败的解决方案

    在Windows系统中,有时候我们需要将Redis作为一个服务运行,以便于在后台长期运行并提供服务,本篇技术博客文章将为你解答在Windows下注册Redis服务失败的一些常见问题,并提供相应的解决方案,需要的朋友可以参考下
    2024-11-11
  • Redisson分布式限流器RRateLimiter的使用及原理小结

    Redisson分布式限流器RRateLimiter的使用及原理小结

    本文主要介绍了Redisson分布式限流器RRateLimiter的使用及原理小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • Redis五大基本数据类型及对应使用场景总结

    Redis五大基本数据类型及对应使用场景总结

    Redis有五种基本数据类型,分别是字符串(String)、哈希(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set),这些基本数据类型使得Redis具备了丰富的数据结构和功能,适用于各种不同的应用场景,本文就给大家详细的介绍一下这五大类型
    2023-08-08
  • 关于使用IDEA的springboot框架往Redis里写入数据乱码问题

    关于使用IDEA的springboot框架往Redis里写入数据乱码问题

    这篇文章主要介绍了用IDEA的springboot框架往Redis里写入数据乱码问题,本文给大家分享解决方法通过图文示例相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • 基于Redis实现阻塞队列的方式

    基于Redis实现阻塞队列的方式

    本文主要讲解基于 Redis 的方式实现异步队列,基于 Redis 的 list 实现队列的方式也有多种,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2021-12-12
  • redis击穿现象如何防止

    redis击穿现象如何防止

    本文主要介绍了redis击穿现象如何防止,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07

最新评论