文章目录
- 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行代码@Overridepublic 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 propertiesif (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;}@Overridepublic 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<>();@PostConstructpublic 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 {@Autowiredprivate 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