前言
在理论 springboot 集成 redis 应用过程中,针对不同类型的业务数据,可能存在不同的 dbindex 中,例如 token 存储 db0,redis 全局锁存储 dbindex1,须要咱们对 RedisTemplate 操作进行扩大,反对单次操作不同的 dbindex
计划
零碎加载时初始化依据 redis 应用库的 dbindex,初始化对应个数的 RedisTemplate,调用时依据 dbindex 获取对应的操作对象实例,本次实现是将 15 个 db 全副初始化
RedisRegist
初始化 redis 的 Factory,线程池配置及 RedisTemplate,StringRedisTemplate 的 Bean 对象
public class RedisRegist implements EnvironmentAware,ImportBeanDefinitionRegistrar {private static final Logger logger = LoggerFactory.getLogger(RedisRegist.class);
private static Map<String, Object> registerBean = new ConcurrentHashMap<>();
private Environment environment;
private Binder binder;
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
this.binder = Binder.get(this.environment);
}
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RedisEntity redisEntity;
try {redisEntity = binder.bind("spring.redis", RedisEntity.class).get();} catch (NoSuchElementException e) {logger.error("redis not setting.");
return;
}
boolean onPrimary = true;
// 依据多个库实例化出多个连接池和 Template
for (int i = 0; i < 15; i++) {
int database = i;
// 单机模式
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
configuration.setHostName(String.valueOf(redisEntity.getHost()));
configuration.setPort(Integer.parseInt(String.valueOf(redisEntity.getPort())));
configuration.setDatabase(database);
String password = redisEntity.getPassword();
if (password != null && !"".equals(password)) {RedisPassword redisPassword = RedisPassword.of(password);
configuration.setPassword(redisPassword);
}
// 池配置
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
RedisProperties.Pool pool = redisEntity.getLettuce().getPoolEntity();
genericObjectPoolConfig.setMaxIdle(pool.getMaxIdle());
genericObjectPoolConfig.setMaxTotal(pool.getMaxActive());
genericObjectPoolConfig.setMinIdle(pool.getMinIdle());
if (pool.getMaxWait() != null) {genericObjectPoolConfig.setMaxWaitMillis(pool.getMaxWait().toMillis());
}
Supplier<LettuceConnectionFactory> lettuceConnectionFactorySupplier = () -> {LettuceConnectionFactory factory = (LettuceConnectionFactory) registerBean.get("LettuceConnectionFactory" + database);
if (factory != null) {return factory;}
LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder();
Duration shutdownTimeout = redisEntity.getLettuce().getShutdownTimeout();
if(shutdownTimeout == null){shutdownTimeout = redisEntity.getTimeout();
}
if (shutdownTimeout != null) {builder.shutdownTimeout(shutdownTimeout);
}
LettuceClientConfiguration clientConfiguration = builder.poolConfig(genericObjectPoolConfig).build();
factory = new LettuceConnectionFactory(configuration, clientConfiguration);
registerBean.put("LettuceConnectionFactory" + database, factory);
return factory;
};
LettuceConnectionFactory lettuceConnectionFactory = lettuceConnectionFactorySupplier.get();
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(LettuceConnectionFactory.class, lettuceConnectionFactorySupplier);
AbstractBeanDefinition factoryBean = builder.getRawBeanDefinition();
factoryBean.setPrimary(onPrimary);
registry.registerBeanDefinition("lettuceConnectionFactory" + database, factoryBean);
// StringRedisTemplate
GenericBeanDefinition stringRedisTemplate = new GenericBeanDefinition();
stringRedisTemplate.setBeanClass(StringRedisTemplate.class);
ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
constructorArgumentValues.addIndexedArgumentValue(0, lettuceConnectionFactory);
stringRedisTemplate.setConstructorArgumentValues(constructorArgumentValues);
stringRedisTemplate.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
registry.registerBeanDefinition("stringRedisTemplate" + database, stringRedisTemplate);
// 定义 RedisTemplate 对象
GenericBeanDefinition redisTemplate = new GenericBeanDefinition();
redisTemplate.setBeanClass(RedisTemplate.class);
redisTemplate.getPropertyValues().add("connectionFactory", lettuceConnectionFactory);
redisTemplate.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
RedisSerializer stringSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// key 采纳 String 的序列化形式,value 采纳 json 序列化形式
redisTemplate.getPropertyValues().add("keySerializer",new StringRedisSerializer());
redisTemplate.getPropertyValues().add("hashKeySerializer",stringSerializer);
redisTemplate.getPropertyValues().add("valueSerializer",jackson2JsonRedisSerializer);
redisTemplate.getPropertyValues().add("hashValueSerializer",stringSerializer);
// 注册 Bean
registry.registerBeanDefinition("redisTemplate" + database, redisTemplate);
//logger.info("Registration redis ({}) !", database);
if (onPrimary) {onPrimary = false;}
}
}
}
RedisManage
RedisTemplate,StringRedisTemplate 的 Bean 对象对立治理定义
public class RedisManage {
private Map<String, RedisTemplate> redisTemplateMap;
private Map<String, StringRedisTemplate> stringRedisTemplateMap;
public RedisManage(Map<String, RedisTemplate> redisTemplateMap,
Map<String, StringRedisTemplate> stringRedisTemplateMap) {
this.redisTemplateMap = redisTemplateMap;
this.stringRedisTemplateMap = stringRedisTemplateMap;
}
public RedisTemplate redisTemplate(int dbIndex) {RedisTemplate redisTemplate = redisTemplateMap.get("redisTemplate" + dbIndex);
return redisTemplate;
}
public StringRedisTemplate stringRedisTemplate(int dbIndex) {StringRedisTemplate stringRedisTemplate = stringRedisTemplateMap.get("stringRedisTemplate" + dbIndex);
stringRedisTemplate.setEnableTransactionSupport(true);
return stringRedisTemplate;
}
public Map<String, RedisTemplate> getRedisTemplateMap() {return redisTemplateMap;}
public Map<String, StringRedisTemplate> getStringRedisTemplateMap() {return stringRedisTemplateMap;}
}
RedisConfig
将操作类 Bean 对象注入道 RedisManage 中
@AutoConfigureBefore({RedisAutoConfiguration.class})
@Import(RedisRegist.class)
@Configuration
public class RedisConfig implements EnvironmentAware, ApplicationContextAware {private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);
private static String key1 = "redisTemplate";
private static String key2 = "stringRedisTemplate";
Map<String, RedisTemplate> redisTemplateMap = new HashMap<>();
Map<String, StringRedisTemplate> stringRedisTemplateMap = new HashMap<>();
private Binder binder;
private Environment environment;
private ApplicationContext applicationContext;
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
this.binder = Binder.get(this.environment);
}
@PostConstruct
public Map<String,RedisTemplate> initRedisTemplate(){
RedisEntity redisEntity;
try {redisEntity = binder.bind("spring.redis", RedisEntity.class).get();} catch (NoSuchElementException e) {throw new RuntimeException("Failed to configure spring.redis:'spring.redis'attribute is not specified and no embedded redis could be configured.");
}
for (int i=0;i<15;i++){
int database = i;
String key = key1 + database;
RedisTemplate redisTemplate = applicationContext.getBean(key , RedisTemplate.class);
if(redisTemplate != null){redisTemplateMap.put(key , redisTemplate);
}
key = key2 + database;
if(stringRedisTemplateMap != null){StringRedisTemplate stringRedisTemplate = applicationContext.getBean(key , StringRedisTemplate.class);
stringRedisTemplateMap.put(key , stringRedisTemplate);
}
}
if(redisTemplateMap.size() == 0 && stringRedisTemplateMap.size() == 0){throw new RuntimeException("load redisTemplate failure , please check spring.redis property config!!!");
}
return redisTemplateMap;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}
@Bean
public RedisManage redisManage(){return new RedisManage(redisTemplateMap , stringRedisTemplateMap);
}
}
RedisUtil
调用 RedisManage 封装具体相干操作调用
@Component
public class RedisUtil {
@Autowired
private RedisManage redisManage;
private int defatuDBIndex= 0;
public void redisTemplateSet(String key, Object value){ValueOperations<Object, Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForValue();
ops.set(key, value);
}
public void redisTemplateSet(String key, Object value,int dbIndex){ValueOperations<Object, Object> ops = redisManage.redisTemplate(dbIndex).opsForValue();
ops.set(key, value);
}
public Object redisTemplateGet(String key){ValueOperations<Object, Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForValue();
return ops.get(key);
}
public Object redisTemplateGet(String key,int dbIndex){ValueOperations<Object, Object> ops = redisManage.redisTemplate(dbIndex).opsForValue();
return ops.get(key);
}
public void redisTemplateRemove(String key){ValueOperations<Object, Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForValue();
ops.getOperations().delete(key);
}
public void redisTemplateRemove(String key,int dbIndex){ValueOperations<Object, Object> ops = redisManage.redisTemplate(dbIndex).opsForValue();
ops.getOperations().delete(key);
}
public void redisTemplateSetForList(String key, Map<String,Object> map){HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForHash();
ops.putAll(key,map);
}
public void redisTemplateSetForList(String key, Map<String,Object> map,int dbIndex){HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(dbIndex).opsForHash();
ops.putAll(key,map);
}
public void redisTemplateSetForList(String key, String hashKey,Object value){HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForHash();
ops.put(key,hashKey,value);
}
public void redisTemplateSetForList(String key, String hashKey,Object value,int dbIndex){HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(dbIndex).opsForHash();
ops.put(key,hashKey,value);
}
public Map<Object, Object> redisTemplateGetForList(String key){HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForHash();
return ops.entries(key);
}
public Map<Object, Object> redisTemplateGetForList(String key,int dbIndex){HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(dbIndex).opsForHash();
return ops.entries(key);
}
public Object redisTemplateGetForList(String key,String hasKey){HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForHash();
return ops.get(key,hasKey);
}
public Object redisTemplateGetForList(String key,String hasKey,int dbIndex){HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(dbIndex).opsForHash();
return ops.get(key,hasKey);
}
public void setExpire(String key,long timeout, final TimeUnit unit,int dbIndex){redisManage.redisTemplate(dbIndex).expire(key,timeout, unit);
}
public void setExpire(String key,long timeout, final TimeUnit unit){redisManage.redisTemplate(defatuDBIndex).expire(key,timeout, unit);
}
public boolean isValid(String key){
boolean flag = false;
if(redisManage.redisTemplate(defatuDBIndex).hasKey(key)){if( redisManage.redisTemplate(defatuDBIndex).getExpire(key,TimeUnit.SECONDS)>0){flag = true;}
}
return flag;
}
public boolean isValid(String key,int dbIndex){
boolean flag = false;
if(redisManage.redisTemplate(dbIndex).hasKey(key)){if( redisManage.redisTemplate(dbIndex).getExpire(key,TimeUnit.SECONDS)>0){flag = true;}
}
return flag;
}
}