1、需求背景
项目需要提供一个管理界面给内部人员操作用户信息,需要在修改用户信息后删除用户的redis缓存。用户所在的区域不同,其redis服务地址也不相同,因此需要管理多个redis连接,且redis要求以集群方式并支持ssl进行连接。
2、实现方案
为每个区域定义一个regionId,用来关联不同区域的redis连接信息,将redis连接信息存于数据库中。采用工具类的方式,构建RedisTemplate对象存于以Map形式存于工具类中的静态变量当中,key为regionId,value为RedisTemplate。每个RedisTemplate构建时机为第一次需要用到它时。
3、具体实现
1、首先是存储redis信息的实体类
public class RedisInfo {private String regionId;private String ip;private int port;private String pwd;// 是否使用sslprivate boolean ssl;// 超时时间private long timeout;
}
2、其次是工具类的实现
public class RedisManage {private static Map<String, RedisTemplate<String, Object>> redisTemplateMap = new HashMap<>();/*** 获取RedisTemplate方法* @param redisInfo 数据库连接信息* @return*/public static RedisTemplate<String, Object> getRedisTemplate(RedisInfo redisInfo) {// 首先从map中获取RedisTemplate<String, Object> redisTemplate = redisTemplateMap.get(redisInfo.getRegionId());// 获取不到就构建一个并存入redisif (redisTemplate == null) {// redis连接配置RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();redisStandaloneConfiguration.setHostName(redisInfo.getIp());redisStandaloneConfiguration.setPort(redisInfo.getPort());redisStandaloneConfiguration.setPassword(RedisPassword.of(redisInfo.getPwd()));// 创建 LettuceClientConfiguration,用于构建LettuceConnectionFactoryLettuceClientConfiguration.LettuceClientConfigurationBuilder builder = LettuceClientConfiguration.builder().commandTimeout(Duration.ofMillis(redisInfo.getTimeout())).shutdownTimeout(Duration.ofMillis(redisInfo.getTimeout()));// 根据需要启用sslif (redisInfo.isSsl()) {builder.useSsl();}// 创建 LettuceConnectionFactory,集群连接的关键LettuceConnectionFactory factory = new LettuceConnectionFactory(redisStandaloneConfiguration, builder.build());// 重要,调用afterPropertiesSet才能正常使用factory.afterPropertiesSet();redisTemplate = new RedisTemplate();redisTemplate.setConnectionFactory(factory);// 将对象属性名序列化成string类型的key,并将string类型的key反序列化成属性名StringRedisSerializer keySerializer = new StringRedisSerializer();// 数据绑定工具,操作redis时需要对key和value进行序列化和反序列化,这个对象可以设置规范ObjectMapper mapper = new ObjectMapper();// 反序列化时遇到未知属性不抛出异常mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);// 序列化空bean时不抛出异常mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);// 反序列化时对象的成员变量与缓存中的对象类型对不上或代码中不存在该类时,不抛出异常mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);// 序列化时间字段时,以文本形式序列序列化而非时间戳mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);// 支持Java8的日期类型,如LocalDate、LocalTime、LocalDateTime等mapper.registerModule(new JavaTimeModule());// 序列化时保留对象类型信息mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);// 序列化和反序列化工具,使用jackson库将对象序列化成json字符串,并将json字符串反序列化成对象,应用了上面ObjectMapper的各项规范RedisSerializer valueSerializer = new GenericJackson2JsonRedisSerializer(mapper);redisTemplate.setKeySerializer(keySerializer);redisTemplate.setValueSerializer((RedisSerializer)valueSerializer);redisTemplate.setHashKeySerializer(keySerializer);redisTemplate.setHashValueSerializer((RedisSerializer)valueSerializer);// 重要,非托管Spring容器构建的RedisTemplate需要调用afterPropertiesSet()方法redisTemplate.afterPropertiesSet();redisTemplateMap.put(redisInfo.getRegionId(), redisTemplate);}return redisTemplate;}}