Redis 多数据源自定义配置 Spring Boot 升级版

news2024/12/22 14:43:19

文章目录

    • 1.前言
    • 2.git 示例地址
    • 3.需求
    • 4.代码实现
      • 4.1 application.properties 配置文件
      • 4.2 获取 application.properties 中的 redis 配置
        • 4.2.1 Environment 对象来获取自定义 redis 配置
      • 4.3 初始化 RedisTemplate 对象,并注册到 Spring IOC 容器
        • 4.3.1 初始化方法
        • 4.3.2 CreateRedisTemplate 方法
        • 4.3.3 getJedisConnectionFactory 方法
      • 4.4 测试 Demo

1.前言

本文为大家提供一个 redis 配置多数据源的实现方案;为上一篇文章【Redis 多数据源 Spring Boot 实现】的升级版本

  • 支持自定义配置
  • 无需写任何其他配置 Java 类
  • application.properties 配置完,直接就可以使用

请注意 spring boot 的相关依赖版本。

2.git 示例地址

git 仓库地址:https://github.com/huajiexiewenfeng/redis-multi-spring/tree/dev-1.0

上个版本为 master 分支,本文为 dev-1.0 分支升级版本

3.需求

1.不需要每一个配置都写一个 Properties 类

2.不需要每一个配置都写一个 RedisTemplate 配置

    @Bean("oneRedisTemplate")
    public RedisTemplate<String, Object> oneRedisTemplate() {...}

    @Bean("twoRedisTemplate")
    public RedisTemplate<String, Object> twoRedisTemplate() {...}

3.使用方法可以与 properties 里面的配置直接对应,比如 oneRedisTemplate

    @Autowired
    @Qualifier("oneRedisTemplate")
    private RedisTemplate<String, Object> redisTemplateOne;

对应 application.properties 中的 multi.redis.one 前缀

multi.redis.one.database=${REDIS_DB_INDEX:2}
multi.redis.one.flushdb=${REDIS_FLUSHDB:false}
multi.redis.one.host=${REDIS_HOST:127.0.0.1}
multi.redis.one.port=${REDIS_PORT:6379}
multi.redis.one.password=123456

其中,multi.redis.one 前缀中的 one 为自定义字符串,可以为任意值

比如 multi.redis.csdn.database 对应的 spring bean name 为 csdnRedisTemplate

    @Autowired
    @Qualifier("csdnRedisTemplate")
    private RedisTemplate<String, Object> redisTemplateOne;

4.代码实现

4.1 application.properties 配置文件

配置文件和原版保持一致

spring.application.name=${APPLICATION_NAME:redis-multiple}
server.port=${SERVER_PORT:22216}

# spring 默认配置
spring.redis.database=${REDIS_DB_INDEX:1}
spring.redis.flushdb=${REDIS_FLUSHDB:false}
spring.redis.host=${REDIS_HOST:127.0.0.1}
spring.redis.port=${REDIS_PORT:6379}
spring.redis.password=123456

#第一个 redis 实例配置
multi.redis.one.database=${REDIS_DB_INDEX:2}
multi.redis.one.flushdb=${REDIS_FLUSHDB:false}
multi.redis.one.host=${REDIS_HOST:127.0.0.1}
multi.redis.one.port=${REDIS_PORT:6379}
multi.redis.one.password=123456


#第二个 redis 实例配置
multi.redis.two.database=${REDIS_DB_INDEX:3}
multi.redis.two.flushdb=${REDIS_FLUSHDB:false}
multi.redis.two.host=${REDIS_HOST:127.0.0.1}
multi.redis.two.port=${REDIS_PORT:6379}
multi.redis.two.password=123456

4.2 获取 application.properties 中的 redis 配置

4.2.1 Environment 对象来获取自定义 redis 配置

实现 EnvironmentAware 接口,获取 Environment 对象,从而来获取我们自定义的配置,核心代码如下:

public class RedisMultiConfiguration implements EnvironmentAware, ApplicationContextAware {
    //...此处省略N行代码
    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
        // 获取 application.properties 对应的 java 类对象
        PropertySource<?> propertySource = ((StandardServletEnvironment) environment).getPropertySources().get("applicationConfig: [classpath:/application.properties]");
        assert propertySource != null;
        Object source = propertySource.getSource();
        // 拿到 redis 配置的前缀集合,例如 multi.redis.xxx...
        Set<String> redisConfigKeys = new HashSet<>();
        if (source instanceof LinkedHashMap) {
            LinkedHashMap<String, Object> map = (LinkedHashMap<String, Object>) source;
            Set<String> keys = map.keySet();
            for (String key : keys) {
                // find multi.redis properties
                if (key.startsWith("multi.redis")) {
                    redisConfigKeys.add(key.substring(0, StrUtils.findNthOccurrence(key, ".", 3)));
                }
            }
        }
        if (redisConfigKeys.isEmpty()) {
            log.error("redis config not found");
        }
        this.redisConfigKeyPrefixSet = redisConfigKeys;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    //...此处省略N行代码
}

后续再通过 environment.getProperty(keyPrefix + "." + REDIS_CONFIG_HOST_NAME) 就可以拿到参数的值

  • keyPrefix = multi.redis.xxx…

4.3 初始化 RedisTemplate 对象,并注册到 Spring IOC 容器

4.3.1 初始化方法
@Slf4j
@Configuration
public class RedisMultiConfiguration implements EnvironmentAware, ApplicationContextAware {

    private Environment environment;

    private ApplicationContext applicationContext;

    private Set<String> redisConfigKeyPrefixSet = new HashSet<>();

    @PostConstruct
    public void initConfig() {
        if (redisConfigKeyPrefixSet.isEmpty()) {
            return;
        }
        for (String keyPrefix : redisConfigKeyPrefixSet) {
            String key = keyPrefix.replace(MULTI_REDIS_CONFIG_PREFIX, "");
            // 创建自定义 RedisTemplate 对象
            RedisTemplate<String, Object> redisTemplate = CreateRedisTemplate(keyPrefix, environment);
            // 注册到 Spring IOC 容器
            ((AnnotationConfigServletWebServerApplicationContext) applicationContext).getBeanFactory().registerSingleton(key + "RedisTemplate", redisTemplate);
        }
    }
    //...此处省略N行代码
}
4.3.2 CreateRedisTemplate 方法
  private RedisTemplate<String, Object> CreateRedisTemplate(String keyPrefix, Environment environment) {
        JedisConnectionFactory jedisConnectionFactory = this.getJedisConnectionFactory(keyPrefix, environment);
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置key的序列化方式
        StringRedisSerializer keySerializer = new StringRedisSerializer();
        template.setConnectionFactory(jedisConnectionFactory);
        template.setKeySerializer(keySerializer);

        // 设置value的序列化方式
        Jackson2JsonRedisSerializer<Object> valueSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是无论什么都可以序列化
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 启用DefaultTyping,方便我们反序列化时知道对象的类型
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        valueSerializer.setObjectMapper(om);
        template.setValueSerializer(valueSerializer);
        // 设置Hash的key和value序列化方式
        template.setHashKeySerializer(keySerializer);
        template.setHashValueSerializer(valueSerializer);

        // 设置value的泛型类型,这样在存取的时候才会序列化和反序列化成设置的对象类型
        // 注意:这里只是设置了value的泛型,key还是String类型
        template.afterPropertiesSet();
        return template;
    }
4.3.3 getJedisConnectionFactory 方法

通过前缀+ environment 去获取对应的配置,再设置到 JedisConnectionFactory 中。

    private JedisConnectionFactory getJedisConnectionFactory(String keyPrefix, Environment environment) {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        // 设置连接池参数,例如最大连接数、最大空闲连接数等
        poolConfig.setMaxTotal(100);
        poolConfig.setMaxIdle(30);
        poolConfig.setMinIdle(10);
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(poolConfig);
        jedisConnectionFactory.setHostName(StrUtils.ifEmpty(environment.getProperty(keyPrefix + "." + REDIS_CONFIG_HOST_NAME), "127.0.0.1"));
        jedisConnectionFactory.setPort(Integer.parseInt(StrUtils.ifEmpty(environment.getProperty(keyPrefix + "." + REDIS_CONFIG_PORT_NAME), "6379")));
        jedisConnectionFactory.setDatabase(Integer.parseInt(StrUtils.ifEmpty(environment.getProperty(keyPrefix + "." + REDIS_CONFIG_DATABASE_NAME), "1")));
        jedisConnectionFactory.setPassword(StrUtils.ifEmpty(environment.getProperty(keyPrefix + "." + REDIS_CONFIG_PASSWORD_NAME), "123456"));
        jedisConnectionFactory.afterPropertiesSet();
        return jedisConnectionFactory;
    }

4.4 测试 Demo

@RestController
public class TestController {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    @Qualifier("oneRedisTemplate")
    private RedisTemplate<String, Object> redisTemplateOne;

    @Autowired
    @Qualifier("twoRedisTemplate")
    private RedisTemplate<String, Object> redisTemplateTwo;

    @GetMapping("/test/redis/add")
    public void profileDetails() {
        redisTemplate.opsForValue().set("test1-dev1.0", "1");
        redisTemplateOne.opsForValue().set("test2-dev1.0", 2);
        redisTemplateTwo.opsForValue().set("test3-dev1.0", 3);
    }

}

浏览器输入

http://127.0.0.1:22216/test/redis/add

执行结果如下:

db1

请添加图片描述

db2

请添加图片描述

db3

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1899077.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python函数语法详解(与C++对比学习)【未完】

一、Python函数的形式 def function_name (参数, ...) -> return value_type:# 函数体return value# 看具体需求# 如果没有return语句&#xff0c;函数执行完毕后也会返回结果# 只是结果为None。return None可以简写为return 1. Python的返回值 在Python3中&#xff0c;提…

新手教师经常会遇到的问题

教育是塑造未来的关键力量&#xff0c;而教师则是这一过程中不可或缺的角色。然而&#xff0c;对于新手教师来说&#xff0c;步入教育行业往往伴随着一系列挑战。本文将探讨新手教师在职业生涯初期可能遇到的一些常见困难&#xff0c;并提供一些应对策略。 教学准备的挑战 新手…

improved-diffusion-main代码理解

目录 一、 TimestepEmbedSequential二、PyTorch之Checkpoint机制三、AttentionBlock四、use_scale_shift_norm 和nanoDiffusion-main相比&#xff0c;improved-diffusion-main代码是相似的&#xff0c;但有几个不是很好理解的地方记录一下。 一、 TimestepEmbedSequential 代码…

栈复用(覆盖栈上的有用数据)

栈复用&#xff08;覆盖栈上的有用数据&#xff09; 程序给的输入长度&#xff0c;不够溢出 到返回值&#xff0c;甚至都 不到bp位置 &#xff0c;这是要考虑覆盖之前函数(或当前函数)的栈上的有用数据&#xff0c;任何利用 程序后续函数调用 时要利用该位置上的数据&#xff…

机器人具身智能Embodied AI

强调智能体&#xff08;如机器人&#xff09;通过物理身体在物理世界中的实时感知、交互和学习来执行任务。 通过物理交互来完成任务的智能系统。它由“本体”&#xff08;即物理身体&#xff09;和“智能体”&#xff08;即智能核心&#xff09;耦合而成&#xff0c;能够在复…

《HIRI-ViT: Scaling Vision Transformer with High Resolution Inputs》解读

期刊&#xff1a;TPAMI 年份&#xff1a;2024 摘要 视觉Transformer(ViT)和卷积神经网络(CNN)的混合深度模型已经成为一类强大的视觉任务骨干。扩大这种混合主干网的输入分辨率自然会增强模型的能力&#xff0c;但不可避免地要承受二次扩展的沉重计算成本。相反&#xff0c;…

SQL索引事务

SQL索引事务 索引 创建主键约束(primary key),唯一约束(unique),外键约束(foreign key)时,会自动创建对应列的索引 1.1 查看索引 show index from 表名 现在这个表中没有索引,那么我们现在将这几个表删除之后创建新表 我们现在建立一个班级表一个学生表,并且学生表与班级表存…

高速PCB设计Tips

在进行原理图输入过程中&#xff0c;需要注意将设计分解为功能块&#xff0c;将所有相关组件放在同一页。例如&#xff0c;以太网相关的组件&#xff0c;通常运行在50MHz或更高频率&#xff0c;在原理图设计中应集中在同一页。清晰标记高速连接和电源连接。差分信号和单端阻抗控…

免费分享:中国三级及以上河流(附下载方法)

河流分级法的分级方法是从源头最小河流开始,称为一级河流;两条一级河流汇合成二级河流;以此类推,三级河流等等;最后是干流。本文将介绍中国三级及以上河流数据。 数据简介 1:100万中国三级及以上河流矢量数据是涵盖了全国范围内三级及以上级别河流的详细地理信息和空间分布。这…

5百多本分章节古籍内容大全ACCESS\EXCEL数据库

很多明清小说现在越来越不容易查看其内容&#xff0c;虽然之前搞到过一份《3万8千多古代文学大全ACCESS数据库》&#xff0c;但简体中文总让我感觉有删减、非原版的印象&#xff0c;今天正好遇到一个好的古籍网站&#xff0c;繁体字繁体文&#xff0c;感觉非常不错&#xff0c;…

期权学习必看圣书:《3小时快学期权》要在哪里看?

今天带你了解期权学习必看圣书&#xff1a;《3小时快学期权》要在哪里看&#xff1f;《3小时快学期权》是一本关于股票期权基础知识的书籍。 它旨在通过简明、易懂的语言和实用的案例&#xff0c;让读者在短时间内掌握股票期权的基本概念、操作方法和投资策略。通过这本书&…

LeetCode刷题记录:(15)三角形最小路径和

知识点&#xff1a;倒叙的动态规划 题目传送 解法一&#xff1a;二维动态规划【容易理解】 class Solution {public int minimumTotal(List<List<Integer>> triangle) {int n triangle.size();if (n 1) {return triangle.get(0).get(0);}// dp[i][j]:走到第i层第…

Gemini for China 大更新,现已上架 Android APP!

官网&#xff1a;https://gemini.fostmar.online/ Android APP&#xff1a;https://gemini.fostmar.online/gemini_1.0.apk 一、Android APP 如果是 Android 设备&#xff0c;则会直接识别到并给下载链接。PC 直接对话即可。 二、聊天记录 现在 Gemini for China&#xff…

QWidget成员函数功能和使用详细说明(四)(文字+用例+代码+效果图)

文章目录 1.测试工程配置2.成员函数2.1 void setParent(QWidget *parent)2.2 void setMouseTracking(bool enable)2.3 bool hasMouseTracking() const2.4 void setPalette(const QPalette &)2.5 const QPalette &palette() const2.6 int QWidget::grabShortcut(const Q…

gradle构建工具

setting.gradle // settings.gradle rootProject.name my-project // 指定根项目名称include subproject1, subproject2 // 指定子项目名称&#xff0c;可选jar包名称 方式一 jar {archiveBaseName my-application // 设置 JAR 文件的基本名称archiveVersion 1.0 // 设置…

实验四 图像增强—灰度变换之直方图变换

一&#xff0e;实验目的 1&#xff0e;掌握灰度直方图的概念及其计算方法&#xff1b; 2&#xff0e;熟练掌握直方图均衡化计算过程&#xff1b;了解直方图规定化的计算过程&#xff1b; 3&#xff0e;了解色彩直方图的概念和计算方法 二&#xff0e;实验内容&#xff1a; …

泰迪智能科技企业项目试岗实训——数据分析类型

当今社会&#xff0c;就业技能的瞩目度正与日俱增。在竞争激烈的就业市场中&#xff0c;重视技能的培养和提升&#xff0c;通过学习与实践&#xff0c;增强自己的竞争力&#xff0c;为未来的职业发展打下坚实的基础&#xff0c;不仅有助于解决各类工作技能问题&#xff0c;更能…

跨境干货|最新注册Google账号方法分享

谷歌账号对做跨境外贸业务的人来说是刚需&#xff0c;目前来说大部分的海外社媒平台、工具都可以用谷歌账号来注册。但是仍然有很多朋友并不知道如何注册这个谷歌账号&#xff0c;今天就来给大家分享2个注册谷歌账号的方法&#xff0c;一个是手机号注册&#xff0c;一个是如何跳…

PEFT - 安装及简单使用

LLM、AIGC、RAG 开发交流裙&#xff1a;377891973 文章目录 一、关于 PEFT二、安装1、使用 PyPI 安装2、使用源码安装 三、快速开始1、训练2、保存模型3、推理4、后续步骤 本文翻译整理自&#xff1a;https://huggingface.co/docs/peft/index 一、关于 PEFT &#x1f917;PEFT…

关于如何做好淘汰 IT 资产数据安全销毁工作的思考 文件销毁 硬盘销毁 数据销毁 物料销毁 文件粉碎

在当今数字化时代&#xff0c;企业的 IT 资产不断更新换代&#xff0c;淘汰的 IT 资产中往往存储着大量的敏感数据。如何确保这些数据在资产淘汰过程中被安全销毁&#xff0c;成为了企业面临的重要挑战。以下是对如何做好淘汰 IT 资产数据安全销毁工作的一些思考。 一、明确数…