這篇文章將為大家詳細(xì)講解有關(guān)springboot中怎么配置創(chuàng)建多個(gè)redis,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
站在用戶的角度思考問題,與客戶深入溝通,找到江海網(wǎng)站設(shè)計(jì)與江海網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:做網(wǎng)站、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、網(wǎng)頁(yè)空間、企業(yè)郵箱。業(yè)務(wù)覆蓋江海地區(qū)。
以下是配置的定義規(guī)范:
spring: redis: timeout: 1000 lettuce: pool: maxActive: 2500 max-wait: 6000 max-idle: 500 min-idle: 100 sentinels: temp1: master: a nodes: ip1:10201,ip2:10202 password: temp2: master: b nodes: ip3:10201,ip4:10202 password: primary: true //是否主要的bean
配置中其他的redis配置還是遵循springboot官方的,但另外擴(kuò)展了一個(gè)sentinels屬性,這個(gè)屬性填充多個(gè)redis 配置信息,由于我們項(xiàng)目主要使用哨兵模式,故這里使用sentinel方式實(shí)現(xiàn)。
其次配置類根據(jù)上面的配置信息可以定義了:
@ConfigurationProperties(prefix = "spring.redis.sentinels") public class RedisExtProperties extends HashMap<String, ExtSentinel>{ private static final long serialVersionUID = 856175258267105532L; public static class ExtSentinel extends Sentinel { private String password; private boolean primary; public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public boolean isPrimary() { return primary; } public void setPrimary(boolean primary) { this.primary = primary; } } }
以上是獲取配置信息的配置類了,接下來(lái)要通過(guò)某些手段去生成StringRedisTemplate的bean了,由于有多個(gè)bean,而且bean的名稱要自己通過(guò)配置文件中定義的,通過(guò)注解@Bean或者xml等方式貌似都無(wú)法達(dá)到目的,這里就利用BeanDefinitionRegistryPostProcessor接口去實(shí)現(xiàn),該接口怎么使用可以去查看spring的一些文檔或者網(wǎng)上搜索都可以找到,這里不在贅述。
這個(gè)接口有兩個(gè)方法postProcessBeanFactory、postProcessBeanDefinitionRegistry,這兩個(gè)方法都可以實(shí)現(xiàn)動(dòng)態(tài)注冊(cè)bean,大家也可以去網(wǎng)上搜索,但是呢,這里卻不能通過(guò)這兩個(gè)方法去實(shí)現(xiàn)動(dòng)態(tài)注冊(cè)StringRedisTemplate的bean,因?yàn)樵诔跏蓟疊eanDefinitionRegistryPostProcessor這個(gè)接口的實(shí)現(xiàn)時(shí),還并沒有完全加載springboot的相關(guān)配置,導(dǎo)致在這兩個(gè)方法里或者通過(guò)注解@Autowired都無(wú)法把RedisExtProperties注入進(jìn)來(lái),即便注入進(jìn)來(lái),也是沒有把相關(guān)配置信息初始化進(jìn)去的,這把就坑了,后面想了半天直接通過(guò)AutowiredAnnotationBeanPostProcessor這個(gè)實(shí)現(xiàn),重寫它的postProcessProperties方法去觸發(fā)動(dòng)態(tài)注冊(cè)bean。
@Component public class RedisCustomFactory extends AutowiredAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor { private final Logger logger = LoggerFactory.getLogger(getClass()); BeanDefinitionRegistry registry; ConfigurableListableBeanFactory factory; AtomicBoolean open = new AtomicBoolean(false); @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { if (!open.get()) { processFields(bean, bean.getClass().getDeclaredFields()); } return super.postProcessProperties(pvs, bean, beanName); } private void processFields(Object bean, Field[] declaredFields) { for (Field field : declaredFields) { if (!open.get() && field.getType().isAssignableFrom(RedisOperations.class)) { register(factory.getBean(RedisProperties.class), factory.getBean(RedisExtProperties.class), factory.getBeanProvider(LettuceClientConfigurationBuilderCustomizer.class)); open.compareAndSet(false, true); } } } private LettuceClientConfigurationBuilder createBuilder(Pool pool) { if (pool == null) { return LettuceClientConfiguration.builder(); } return new PoolBuilderFactory().createBuilder(pool); } // private void customize(LettuceClientConfiguration.LettuceClientConfigurationBuilder builder, // ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers) { // builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); // } private LettuceClientConfigurationBuilder applyProperties( LettuceClientConfiguration.LettuceClientConfigurationBuilder builder, RedisProperties properties) { if (properties.isSsl()) { builder.useSsl(); } if (properties.getTimeout() != null) { builder.commandTimeout(properties.getTimeout()); } if (properties.getLettuce() != null) { RedisProperties.Lettuce lettuce = properties.getLettuce(); if (lettuce.getShutdownTimeout() != null && !lettuce.getShutdownTimeout().isZero()) { builder.shutdownTimeout(properties.getLettuce().getShutdownTimeout()); } } return builder; } private LettuceClientConfiguration getLettuceClientConfiguration(ClientResources clientResources, Pool pool, RedisProperties properties, ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers) { LettuceClientConfigurationBuilder builder = createBuilder(pool); applyProperties(builder, properties); builder.clientResources(clientResources); // customize(builder, builderCustomizers); return builder.build(); } private List<RedisNode> createSentinels(RedisProperties.Sentinel sentinel) { List<RedisNode> nodes = new ArrayList<>(); for (String node : sentinel.getNodes()) { try { String[] parts = StringUtils.split(node, ":"); Assert.state(parts.length == 2, "Must be defined as 'host:port'"); nodes.add(new RedisNode(parts[0], Integer.valueOf(parts[1]))); } catch (RuntimeException ex) { throw new IllegalStateException("Invalid redis sentinel " + "property '" + node + "'", ex); } } return nodes; } protected RedisSentinelConfiguration getSentinelConfig(ExtSentinel sentinelProperties, RedisProperties properties) { if (sentinelProperties != null) { RedisSentinelConfiguration config = new RedisSentinelConfiguration(); config.master(sentinelProperties.getMaster()); config.setSentinels(createSentinels(sentinelProperties)); if (sentinelProperties.getPassword() != null) { config.setPassword(RedisPassword.of(sentinelProperties.getPassword())); } config.setDatabase(properties.getDatabase()); return config; } return null; } private LettuceConnectionFactory createLettuceConnectionFactory(LettuceClientConfiguration clientConfiguration, RedisSentinelConfiguration redisSentinelConfiguration, RedisProperties properties) { return new LettuceConnectionFactory(redisSentinelConfiguration, clientConfiguration); } private LettuceConnectionFactory redisConnectionFactory(ClientResources clientResources, RedisSentinelConfiguration redisSentinelConfiguration, RedisProperties properties, ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers) throws UnknownHostException { LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(clientResources, properties.getLettuce().getPool(), properties, null); return createLettuceConnectionFactory(clientConfig, redisSentinelConfiguration, properties); } public synchronized void register(RedisProperties properties, RedisExtProperties extProperties, ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers) throws BeansException { if (extProperties == null) { return; } extProperties.forEach((name, sentinel) -> { try { if (!factory.containsBeanDefinition(name + "RedisTemplate")) { logger.info("{} -----> {}", name, sentinel.isPrimary()); DefaultClientResources res = DefaultClientResources.create(); BeanDefinitionBuilder builder0 = BeanDefinitionBuilder .genericBeanDefinition(DefaultClientResources.class, () -> res); BeanDefinition beanDefinition0 = builder0.getRawBeanDefinition(); beanDefinition0.setPrimary(sentinel.isPrimary()); beanDefinition0.setDestroyMethodName("shutdown"); registry.registerBeanDefinition(name + "DefaultClientResources", beanDefinition0); LettuceConnectionFactory ref = redisConnectionFactory(res, getSentinelConfig(sentinel, properties), properties, builderCustomizers); BeanDefinitionBuilder builder1 = BeanDefinitionBuilder .genericBeanDefinition(RedisConnectionFactory.class, () -> ref); BeanDefinition beanDefinition1 = builder1.getRawBeanDefinition(); beanDefinition1.setPrimary(sentinel.isPrimary()); registry.registerBeanDefinition(name + "RedisConnectionFactory", beanDefinition1); BeanDefinitionBuilder builder2 = BeanDefinitionBuilder .genericBeanDefinition(StringRedisTemplate.class, () -> { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(ref); return template; }); BeanDefinition beanDefinition2 = builder2.getRawBeanDefinition(); beanDefinition2.setPrimary(sentinel.isPrimary()); registry.registerBeanDefinition(name + "RedisTemplate", beanDefinition2); } } catch (Exception ex) { logger.error("register redisProperties error", ex); } }); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException { this.factory = factory; } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { this.registry = registry; } @Override public int getOrder() { return super.getOrder() - 1; } }
public class PoolBuilderFactory { public LettuceClientConfigurationBuilder createBuilder(Pool properties) { return LettucePoolingClientConfiguration.builder().poolConfig(getPoolConfig(properties)); } private GenericObjectPoolConfig<?> getPoolConfig(Pool properties) { GenericObjectPoolConfig<?> config = new GenericObjectPoolConfig<>(); config.setMaxTotal(properties.getMaxActive()); config.setMaxIdle(properties.getMaxIdle()); config.setMinIdle(properties.getMinIdle()); if (properties.getTimeBetweenEvictionRuns() != null) { config.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRuns().toMillis()); } if (properties.getMaxWait() != null) { config.setMaxWaitMillis(properties.getMaxWait().toMillis()); } return config; } }
根據(jù)代碼的細(xì)節(jié),可以看到sentinels其實(shí)是一個(gè)map,會(huì)把sentinels的key和RedisTemplate拼接成bean的名字,所以在使用的過(guò)程中,如果有primary配置的直接使用@Autowired就可以直接注入了,其他的則@Qualifier+@Autowired既可以注入了。
@Autowired private StringRedisTemplate stringRedisTemplate;//對(duì)應(yīng)的master 為b的 @Autowired @Qualifier("temp1RedisTemplate") private StringRedisTemplate microblogRedisTemplate;//對(duì)應(yīng)的master 為a的
關(guān)于springboot中怎么配置創(chuàng)建多個(gè)redis就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
當(dāng)前名稱:springboot中怎么配置創(chuàng)建多個(gè)redis
文章來(lái)源:http://muchs.cn/article30/pdjcpo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、外貿(mào)網(wǎng)站建設(shè)、面包屑導(dǎo)航、電子商務(wù)、網(wǎng)站策劃、標(biāo)簽優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)