Springboot 实现Redis 同数据源动态切换db
默认redis使用的是db 0,而我们自己在配置连接的时候可以设置默认使用db ,如:
那么怎么去实现动态 去切换自己想使用的db呢?
LettuceConnectionFactory connectionFactory = (LettuceConnectionFactory) redisTemplate.getConnectionFactory();
connectionFactory.setDatabase(num);
依赖
<!-- Redis相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 如果使用Lettuce作为连接池,需要引入commons-pool2包,否则会报错bean注入失败 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
yml
redis:
host: 192.168.222.157
port: 7002
# password: xatgood
database: 0
timeout: 6000 # 连接超时时间(毫秒)默认是2000ms
lettuce:
pool:
max-active: 200 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 100 # 连接池中的最大空闲连接
min-idle: 50 # 连接池中的最小空闲连接
shutdown-timeout: 500 # 关闭超时时间
# sentinel: # 哨兵模式
# master: mymaster
# nodes: 192.168.222.155:26379,192.168.222.155:26380,192.168.222.155:26381
# cluster: #集群模式
# nodes:
# - 192.168.222.157:6379
# - 192.168.222.157:6380
# - 192.168.222.157:6381
# - 192.168.222.157:6389
# - 192.168.222.157:6390
# - 192.168.222.157:6391
max-redirects: 3 # 获取失败 最大重定向次数
新建RedisConfig配置类
第一类:
/**
* Redis配置类
*/
@Configuration
public class RedisConfig {
@Resource
private RedisTemplate redisTemplate;
public RedisTemplate setDataBase(int num) {
LettuceConnectionFactory connectionFactory = (LettuceConnectionFactory) redisTemplate.getConnectionFactory();
if (connectionFactory != null && num != connectionFactory.getDatabase()) {
connectionFactory.setDatabase(num);
this.redisTemplate.setConnectionFactory(connectionFactory);
connectionFactory.resetConnection();
connectionFactory.afterPropertiesSet();
}
return redisTemplate;
}
/**
* 序列化注入spring容器的RedisTemplate
*
* @return
*/
@Bean
public RedisTemplate<Serializable, Object> getRedisTemplate() {
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
//使用StringRedisSerializer来序列化和反序列化redis的key值
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(serializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
// redisTemplate.setEnableTransactionSupport(true);
return redisTemplate;
}
}
第二类
package com.zdyl.wxapplet.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; import org.springframework.data.redis.connection.*; 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.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Redis配置类 */ @Slf4j @Configuration public class RedisConfig { @Resource private RedisProperties redisProperties; @Resource private RedisTemplate redisTemplate; public static Map<Integer, RedisTemplate<Serializable, Object>> redisTemplateMap = new HashMap<>(); @PostConstruct public void initRedisTemp() throws Exception { for (int i = 0; i <= 15; i++) { redisTemplateMap.put(i, getRedisTemplate(i)); } } /** * 获取redisTemplate实例 * * @param db * @return */ private RedisTemplate<Serializable, Object> getRedisTemplate(int db) { final RedisTemplate<Serializable, Object> redisTemplate = new RedisTemplate<>(); LettuceConnectionFactory factory = factory(); factory.setDatabase(db); redisTemplate.setConnectionFactory(factory); return serializer(redisTemplate); } /** * redis单机配置 * * @return */ private RedisStandaloneConfiguration redisConfiguration() { RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); redisStandaloneConfiguration.setHostName(redisProperties.getHost()); redisStandaloneConfiguration.setPort(redisProperties.getPort()); //设置密码 if (redisProperties.getPassword() != null) { redisStandaloneConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword())); } return redisStandaloneConfiguration; } /** * redis哨兵配置 * * @return */ private RedisSentinelConfiguration getSentinelConfiguration() { RedisProperties.Sentinel sentinel = redisProperties.getSentinel(); if (sentinel != null) { RedisSentinelConfiguration config = new RedisSentinelConfiguration(); config.setMaster(sentinel.getMaster()); if (!StringUtils.isEmpty(redisProperties.getPassword())) { config.setPassword(RedisPassword.of(redisProperties.getPassword())); } config.setSentinels(createSentinels(sentinel)); return config; } return null; } /** * 获取哨兵节点 * * @param sentinel * @return */ private List<RedisNode> createSentinels(RedisProperties.Sentinel sentinel) { List<RedisNode> nodes = new ArrayList<>(); for (String node : sentinel.getNodes()) { String[] parts = StringUtils.split(node, ":"); Assert.state(parts.length == 2, "redis哨兵地址配置不合法!"); nodes.add(new RedisNode(parts[0], Integer.valueOf(parts[1]))); } return nodes; } /** * redis集群配置 * * @return */ private RedisClusterConfiguration getRedisClusterConfiguration() { RedisProperties.Cluster cluster = redisProperties.getCluster(); if (cluster != null) { RedisClusterConfiguration config = new RedisClusterConfiguration(); config.setClusterNodes(createCluster(cluster)); if (!StringUtils.isEmpty(redisProperties.getPassword())) { config.setPassword(RedisPassword.of(redisProperties.getPassword())); } config.setMaxRedirects(redisProperties.getCluster().getMaxRedirects()); return config; } return null; } /** * 获取集群节点 * * @param cluster * @return */ private List<RedisNode> createCluster(RedisProperties.Cluster cluster) { List<RedisNode> nodes = new ArrayList<>(); for (String node : cluster.getNodes()) { String[] parts = StringUtils.split(node, ":"); Assert.state(parts.length == 2, "redis哨兵地址配置不合法!"); nodes.add(new RedisNode(parts[0], Integer.valueOf(parts[1]))); } return nodes; } /** * 连接池配置 * * @return */ private GenericObjectPoolConfig redisPool() { GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig(); genericObjectPoolConfig.setMaxIdle(redisProperties.getLettuce().getPool().getMaxIdle()); genericObjectPoolConfig.setMinIdle(redisProperties.getLettuce().getPool().getMinIdle()); genericObjectPoolConfig.setMaxTotal(redisProperties.getLettuce().getPool().getMaxActive()); genericObjectPoolConfig.setTestOnBorrow(true); genericObjectPoolConfig.setTestWhileIdle(true); genericObjectPoolConfig.setTestOnReturn(false); genericObjectPoolConfig.setMaxWaitMillis(5000); return genericObjectPoolConfig; } /** * redis客户端配置 * * @return */ private LettuceClientConfiguration clientConfiguration() { LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder(); builder.commandTimeout(redisProperties.getLettuce().getShutdownTimeout()); builder.shutdownTimeout(redisProperties.getLettuce().getShutdownTimeout()); builder.poolConfig(redisPool()); LettuceClientConfiguration lettuceClientConfiguration = builder.build(); return lettuceClientConfiguration; } /** * redis获取连接工厂 * * @return */ @Scope(scopeName = "prototype") private LettuceConnectionFactory factory() { //根据配置和客户端配置创建连接 LettuceConnectionFactory lettuceConnectionFactory = null; if (redisProperties.getSentinel() == null && redisProperties.getCluster() == null) { //单机模式 lettuceConnectionFactory = new LettuceConnectionFactory(redisConfiguration(), clientConfiguration()); lettuceConnectionFactory.afterPropertiesSet(); } else if (redisProperties.getCluster() == null) { //哨兵模式 lettuceConnectionFactory = new LettuceConnectionFactory(getSentinelConfiguration(), clientConfiguration()); lettuceConnectionFactory.afterPropertiesSet(); } else { //集群模式 lettuceConnectionFactory = new LettuceConnectionFactory(getRedisClusterConfiguration(), clientConfiguration()); lettuceConnectionFactory.afterPropertiesSet(); } return lettuceConnectionFactory; } /** * 序列化 * * @param redisTemplate * @return */ private RedisTemplate<Serializable, Object> serializer(RedisTemplate redisTemplate) { Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); serializer.setObjectMapper(mapper); //使用StringRedisSerializer来序列化和反序列化redis的key值 redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(serializer); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new StringRedisSerializer()); redisTemplate.afterPropertiesSet(); // redisTemplate.setEnableTransactionSupport(true); return redisTemplate; } }
Redis工具类
package com.zdyl.gateway.common.utils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import com.google.gson.Gson; import com.zdyl.gateway.config.RedisConfig; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.ListOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.io.Serializable; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; /** * 单机版redis工具类 */ @Component public class RedisUtil { @Resource private RedisConfig redisConfig; private final static Gson gson = new Gson(); /** * 根据db获取对应的redisTemplate实例 * * @param db * @return redisTemplate实例 */ public RedisTemplate<Serializable, Object> getRedisTemplateByDb(final int db) { return redisConfig.getRedisTemplate(db); } /** * 设置缓存 * * @param key 缓存key * @param value 缓存value */ public void setString(String key, String value, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); redisTemplate.opsForValue().set(key, value); } /** * 设置缓存,并且自己指定过期时间 * * @param key * @param value * @param expireTime 过期时间 */ public void setString(String key, String value, int expireTime, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); redisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.SECONDS); } /** * 设置缓存对象,可指定DB * * @param key 缓存key * @param obj 缓存value */ public <T> void setObject(String key, T obj, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); redisTemplate.opsForValue().set(key, obj); } /** * 新增hashMap值 * * @param key * @param hashKey * @param hashValue * @param db * @return void * @author WangJing * @date 2019年10月26日 9:22 */ public <T> void hashPutString(Serializable key, Serializable hashKey, String hashValue, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); HashOperations<Serializable, Serializable, Serializable> operations = redisTemplate.opsForHash(); operations.put(key, hashKey, hashValue); } /** * 以map集合的形式添加键值对 * * @param key * @param maps * @param db * @return void * @author Sunhj * @date 2019年10月26日 9:56 */ public void hashPutAll(String key, Map<Serializable, Serializable> maps, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); HashOperations<Serializable, Serializable, Serializable> operations = redisTemplate.opsForHash(); operations.putAll(key, maps); } /** * 获取变量中的键值对 * {key3=value3, key1=value1, key5=value5, key4=value4, key2=value2} * * @param db * @param key * @return java.util.Map<String, String> * @author wangj * @date 2019年10月26日 8:47 */ public <T> Map<Object, Object> hashGetAll(int db, Serializable key) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); return redisTemplate.opsForHash().entries(key); } /** * 判断key是否存在 * * @param key * @param db * @return java.util.Map<String, String> * @author wangj * @date 2019年10月26日 8:47 */ public <T> Boolean hashHasKey(Serializable key, Serializable hahsKey, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); return redisTemplate.opsForHash().hasKey(key, hahsKey); } /** * 获取hash表中存在的所有的键 * * @param key * @param db * @return java.util.List<java.lang.String> * @author Sunhj * @date 2019年10月26日 10:58 */ public Set<Object> hashGetAllHashKeys(Serializable key, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); return redisTemplate.opsForHash().keys(key); } /** * 获取hash表中存在的所有的值 * * @param key * @param db * @return java.util.List<java.lang.String> * @author Sunhj * @date 2019年10月26日 10:58 */ public List<Object> hashGetAllHashValues(Serializable key, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); return redisTemplate.opsForHash().values(key); } /** * 根据key,hashKey * 获取hash表中存在的单个值 * * @param key * @param db * @return java.util.List<java.lang.String> * @author Sunhj * @date 2019年10月26日 10:58 */ public Object hashGetObject(Serializable key, Serializable hashKey, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); return redisTemplate.opsForHash().get(key, hashKey); } /** * 删除一个或者多个hash表字段 * * @param key * @param db * @param fields * @return java.lang.Long * @author Sunhj * @date 2019年10月26日 10:15 */ public Long hashDelete(Serializable key, int db, Serializable... fields) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); HashOperations<Serializable, Serializable, Serializable> operations = redisTemplate.opsForHash(); return operations.delete(key, (Object) fields); } /** * 删除一个hash表字段 * * @param key * @param db * @param fields * @return java.lang.Long * @author Sunhj * @date 2019年10月26日 10:15 */ public boolean hashDeleteOne(Serializable key, String fields, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); HashOperations<Serializable, Serializable, Serializable> operations = redisTemplate.opsForHash(); return operations.delete(key, fields) == 1; } /** * 设置缓存对象 * * @param key 缓存key * @param obj 缓存value */ public <T> void setObject(String key, T obj, int expireTime, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); redisTemplate.opsForValue().set(key, obj, expireTime, TimeUnit.SECONDS); } /** * 获取指定key的缓存 * * @param key---JSON.parseObject(value, User.class); */ public String getObject(String key, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); Object o = redisTemplate.opsForValue().get(key); return o == null ? null : toJson(o); } /** * 判断当前key值 是否存在 * * @param key */ public boolean hasKey(String key, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); return redisTemplate.hasKey(key); } /** * 获取指定key的缓存 * * @param key */ public String getString(String key, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); Object o = redisTemplate.opsForValue().get(key); String s = o == null ? null : toJson(o); return s; } /** * 删除指定key的缓存 * * @param key */ public void delete(String from, String key, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); redisTemplate.delete(key); } /** * @param key * @throws * @Title: expire * @Description: 更新key的失效时间 */ public Boolean expire(String key, int seconds, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); return redisTemplate.expire(key, seconds, TimeUnit.SECONDS); } /** * 移除并获取列表中第一个元素 * * @param key * @param db * @return void * @author sunhj * @date 2019年10月26日 14:35 */ public String listLeftPop(Serializable key, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); Object leftPop = redisTemplate.opsForList().leftPop(key); if (leftPop == null) { return null; } return JSON.toJSONString(leftPop); } /** * 移除并获取列表最后一个元素 * * @param key * @param db * @return java.lang.Object * @author sunhj * @date 2019年10月26日 14:40 */ public String listRightPop(Serializable key, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); ListOperations<Serializable, Object> operations = redisTemplate.opsForList(); Object x = operations.rightPop(key); if (x == null) { return null; } return JSON.toJSONString(x); } /** * 获取变量中的指定map键是否有值,如果存在该map键则获取值,没有则返回null。 * * @param key * @param field * @param db * @return T * @author Sunhj * @date 2019年10月26日 8:41 */ public <T> T hashGet(Serializable key, Serializable field, Class<T> t, int db) { try { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); Object o = redisTemplate.opsForHash().get(key, field); String s = o == null ? null : toJson(o); return s == null ? null : fromJson(s, t); } catch (Exception e) { return null; } } /** * 获取变量中的指定map键是否有值,如果存在该map键则获取值(String格式),没有则返回null。 * * @param key * @param field * @param db * @return T * @author Sunhj * @date 2019年10月26日 8:41 */ public String hashGetString(Serializable key, Serializable field, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); HashOperations<Serializable, Serializable, Serializable> operations = redisTemplate.opsForHash(); try { Serializable serializable = operations.get(key, field); if (serializable != null) { return serializable.toString(); } return null; } catch (Exception e) { return null; } } /** * 获取变量中的键值对 ?? * * @param key * @param db * @return java.util.Map<String, String> * @author Sunhj * @date 2019年10月26日 8:47 */ public <T> Map<String, T> hashGetAll(Serializable key, Class<T> t, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); HashOperations<Serializable, Serializable, Serializable> operations = redisTemplate.opsForHash(); Map<Serializable, Serializable> x = operations.entries(key); Map<String, T> map = new HashMap<>(); try { for (Serializable xa : x.keySet()) { String keyValue = x.get(xa).toString(); map.put(xa.toString(), JSON.parseObject(keyValue, t)); } return map; } catch (Exception e) { return null; } } /** * 新增hashMap值 * * @param key * @param hashKey * @param hashValue * @param db * @return void * @author Sunhj * @date 2019年10月26日 9:22 */ public <T> boolean hashPut(Serializable key, Serializable hashKey, T hashValue, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); HashOperations<Serializable, Serializable, Serializable> operations = redisTemplate.opsForHash(); operations.put(key, hashKey, JSON.toJSONString(hashValue, SerializerFeature.WriteMapNullValue)); return true; } /** * 查看hash表中指定字段是否存在 * * @param key * @param field * @param db * @return boolean * @author Sunhj * @date 2019年10月26日 10:32 */ public boolean hashExists(Serializable key, Serializable field, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); HashOperations<Serializable, Serializable, Serializable> operations = redisTemplate.opsForHash(); return operations.hasKey(key, field); } /** * 存储在list的头部,即添加一个就把它放在最前面的索引处 * * @param key * @param value * @param db * @return java.lang.Long * @author sunhj * @date 2019年10月26日 14:03 */ public Long listLeftPush(Serializable key, Serializable value, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); ListOperations<Serializable, Object> operations = redisTemplate.opsForList(); return operations.leftPush(key, value); } /** * 获取所有的KEY * * @param key */ public List<Object> getHashKeys(String key, int db) { RedisTemplate<Serializable, Object> redisTemplate = getRedisTemplateByDb(db); List<Object> values = redisTemplate.opsForHash().values(key); return values; } /** * Object转成JSON数据 */ private String toJson(Object object) { if (object instanceof Integer || object instanceof Long || object instanceof Float || object instanceof Double || object instanceof Boolean || object instanceof String) { return String.valueOf(object); } return gson.toJson(object); } /** * JSON数据,转成Object */ public <T> T fromJson(String json, Class<T> clazz) { return gson.fromJson(json, clazz); } }
ok,最后简单的切换使用演示:
@Slf4j @RunWith(SpringRunner.class) @SpringBootTest public class ShaobingApplicationTests { @Resource private RedisUtils redisUtils; @Resource private RedisTemplate redisTemplate; @Test public void testStringRedisTemplate() throws InterruptedException { redisUtils.setObject("1","测试1",1); redisUtils.setObject("2","测试2",2); redisUtils.setObject("3","测试3",3); } }
ok,该篇教程就暂且到此结束。