redis 在 spring容器的核心类
- StringRedisTemplate 和 RedisTemplate
- 客户端工厂 LettuceConnectionFactory 也可以使用 JedisConnectionFactory
配置文件
redis:base:host: 192.168.8.165port: 6379database: 0timeout: 3000lettuce:pool:min-idle: 5max-idle: 10max-active: 8max-wait: 1msreport:host: cache164.e6xayf.comport: 6379database: 12timeout: 3000lettuce:pool:min-idle: 5max-idle: 10max-active: 8max-wait: 1ms
配置类
参照 RedisAutoConfiguration 和 LettuceConnectionConfiguration
package com.alibaba.project.config;import io.lettuce.core.resource.ClientResources;import io.lettuce.core.resource.DefaultClientResources;import org.apache.commons.pool2.impl.GenericObjectPoolConfig;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.autoconfigure.data.redis.RedisProperties;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.connection.RedisPassword;import org.springframework.data.redis.connection.RedisStandaloneConfiguration;import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;import org.springframework.data.redis.core.StringRedisTemplate;/*** @author demon* @date 2021/3/1 11:08*/@Configuration@ConfigurationProperties(prefix = "redis")public class RedisConfig {private RedisProperties base;private RedisProperties report;@Bean(destroyMethod = "shutdown")@ConditionalOnMissingBean(ClientResources.class)public DefaultClientResources lettuceClientResources() {return DefaultClientResources.create();}@Bean(name = "baseStringRedisTemplate")@Primarypublic StringRedisTemplate baseStringRedisTemplate(@Qualifier("baseLettuceConnectionFactory") RedisConnectionFactory redisConnectionFactory) {StringRedisTemplate template = new StringRedisTemplate();template.setConnectionFactory(redisConnectionFactory);return template;}@Bean(name = "baseLettuceConnectionFactory")@Primarypublic LettuceConnectionFactory baseLettuceConnectionFactory(ClientResources clientResources) {RedisStandaloneConfiguration redis1StandaloneConfiguration = getStandaloneConfig(base);LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(clientResources, base);return new LettuceConnectionFactory(redis1StandaloneConfiguration, clientConfig);}@Bean(name = "reportStringRedisTemplate")public StringRedisTemplate reportStringRedisTemplate(@Qualifier("reportLettuceConnectionFactory") RedisConnectionFactory redisConnectionFactory) {StringRedisTemplate template = new StringRedisTemplate();template.setConnectionFactory(redisConnectionFactory);return template;}@Bean(name = "reportLettuceConnectionFactory")public LettuceConnectionFactory reportLettuceConnectionFactory(ClientResources clientResources) {RedisStandaloneConfiguration redis1StandaloneConfiguration = getStandaloneConfig(report);LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(clientResources, report);return new LettuceConnectionFactory(redis1StandaloneConfiguration, clientConfig);}/*** redis standalone config** @param redisProperties redis 配置参数* @return RedisStandaloneConfiguration*/private RedisStandaloneConfiguration getStandaloneConfig(RedisProperties redisProperties) {RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();config.setHostName(redisProperties.getHost());config.setPort(redisProperties.getPort());config.setPassword(RedisPassword.of(redisProperties.getPassword()));config.setDatabase(redisProperties.getDatabase());return config;}/*** 构建 LettuceClientConfiguration** @param clientResources clientResources* @param redisProperties redisProperties* @return LettuceClientConfiguration*/private LettuceClientConfiguration getLettuceClientConfiguration(ClientResources clientResources,RedisProperties redisProperties) {LettuceClientConfiguration.LettuceClientConfigurationBuilder builder =createBuilder(redisProperties.getLettuce().getPool());if (redisProperties.isSsl()) {builder.useSsl();}if (redisProperties.getTimeout() != null) {builder.commandTimeout(redisProperties.getTimeout());}if (redisProperties.getLettuce() != null) {RedisProperties.Lettuce lettuce = redisProperties.getLettuce();if (lettuce.getShutdownTimeout() != null&& !lettuce.getShutdownTimeout().isZero()) {builder.shutdownTimeout(redisProperties.getLettuce().getShutdownTimeout());}}builder.clientResources(clientResources);return builder.build();}/*** 创建 LettuceClientConfigurationBuilder** @param pool 连接池配置* @return LettuceClientConfigurationBuilder*/private LettuceClientConfiguration.LettuceClientConfigurationBuilder createBuilder(RedisProperties.Pool pool) {if (pool == null) {return LettuceClientConfiguration.builder();}return LettucePoolingClientConfiguration.builder().poolConfig(getPoolConfig(pool));}/*** pool config** @param properties redis 参数配置* @return GenericObjectPoolConfig*/private GenericObjectPoolConfig getPoolConfig(RedisProperties.Pool properties) {GenericObjectPoolConfig config = new GenericObjectPoolConfig();config.setMaxTotal(properties.getMaxActive());config.setMaxIdle(properties.getMaxIdle());config.setMinIdle(properties.getMinIdle());if (properties.getMaxWait() != null) {config.setMaxWaitMillis(properties.getMaxWait().toMillis());}return config;}public RedisProperties getBase() {return base;}public void setBase(RedisProperties base) {this.base = base;}public RedisProperties getReport() {return report;}public void setReport(RedisProperties report) {this.report = report;}}
使用
使用 Qualifier 注解指定 StringRedisTemplate 完成注入
优化
上面如果在加一个redis 配置,还需要修改redis 配置类,这是不优雅的。我们可以通过配置文件指定一个 primary 的redis 数据源,其他通过名称+StringRedisTemplate 的方式注入。只增加配置文件,不修改代码,完成注入。这才是比较优雅的解决方案。
注入时,我们通过 beanFactory 以编程的方式注入,这就不会存在硬编码。
public synchronized void setCosBean(String beanName, Class<?> clazz, ConstructorArgumentValues original) {DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();if (beanFactory.containsBean(beanName)) {return;}GenericBeanDefinition definition = new GenericBeanDefinition();definition.setBeanClass(clazz);if(beanName.startsWith(primaryKey)){definition.setPrimary(true);}//属性赋值definition.setConstructorArgumentValues(new ConstructorArgumentValues(original));//注册到spring上下文beanFactory.registerBeanDefinition(beanName, definition);}
