diff --git a/yexuejc-springboot-base/src/main/java/com/yexuejc/springboot/base/autoconfigure/MutiRedisAutoConfiguration.java b/yexuejc-springboot-base/src/main/java/com/yexuejc/springboot/base/autoconfigure/MutiRedisAutoConfiguration.java index b932d88..33dc3cf 100644 --- a/yexuejc-springboot-base/src/main/java/com/yexuejc/springboot/base/autoconfigure/MutiRedisAutoConfiguration.java +++ b/yexuejc-springboot-base/src/main/java/com/yexuejc/springboot/base/autoconfigure/MutiRedisAutoConfiguration.java @@ -1,19 +1,22 @@ package com.yexuejc.springboot.base.autoconfigure; import org.apache.commons.pool2.impl.GenericObjectPool; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; +import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Cluster; +import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Sentinel; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.annotation.Order; +import org.springframework.data.redis.connection.RedisClusterConfiguration; 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.jedis.JedisClientConfiguration; +import org.springframework.data.redis.connection.RedisNode; +import org.springframework.data.redis.connection.RedisSentinelConfiguration; import org.springframework.data.redis.connection.jedis.JedisConnection; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisOperations; @@ -21,17 +24,25 @@ import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; 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 redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPoolConfig; +import java.net.URI; +import java.net.URISyntaxException; import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; /** - * 多个database配置 + * 对redis 多个databasse封装 * * @author maxf - * @PackageName com.yexuejc.springboot.base.autoconfigure + * @version 1.0 + * @ClassName MutiRedisAutoConfiguration * @Description - * @date 2018/9/26 15:27 + * @date 2018/11/1 10:31 */ @Configuration @ConditionalOnClass({JedisConnection.class, RedisOperations.class, Jedis.class}) @@ -39,6 +50,7 @@ import java.net.UnknownHostException; @Order(1) @ConditionalOnProperty(name = "yexuejc.autoconfigure.redis.enable", matchIfMissing = false) public class MutiRedisAutoConfiguration { + public static final String BEAN_REDIS_FACTORY0 = "redisConnectionFactory"; public static final String BEAN_REDIS_TEMPLATE0 = "redisTemplate"; public static final String BEAN_REDIS_STRING_TEMPLATE0 = "stringRedisTemplate"; @@ -71,6 +83,9 @@ public class MutiRedisAutoConfiguration { public static final String BEAN_REDIS_TEMPLATE9 = "redis-template-9"; public static final String BEAN_REDIS_STRING_TEMPLATE9 = "redis-string-template-9"; + /** + * Redis connection configuration. + */ @Configuration @ConditionalOnClass(GenericObjectPool.class) @ConditionalOnProperty(name = "yexuejc.autoconfigure.redis.enable", matchIfMissing = false) @@ -78,87 +93,197 @@ public class MutiRedisAutoConfiguration { private final RedisProperties properties; - public RedisConnectionConfiguration(RedisProperties properties) { + private final RedisSentinelConfiguration sentinelConfiguration; + + private final RedisClusterConfiguration clusterConfiguration; + + public RedisConnectionConfiguration(RedisProperties properties, + ObjectProvider sentinelConfiguration, + ObjectProvider clusterConfiguration) { this.properties = properties; + this.sentinelConfiguration = sentinelConfiguration.getIfAvailable(); + this.clusterConfiguration = clusterConfiguration.getIfAvailable(); } @Primary @Bean(BEAN_REDIS_FACTORY0) @ConditionalOnProperty(name = "yexuejc.redis.db0", matchIfMissing = true) public JedisConnectionFactory redisConnectionFactory0() throws UnknownHostException { - return createJedisConnectionFactory(0); + return applyProperties(createJedisConnectionFactory(), 0); } @Bean(BEAN_REDIS_FACTORY1) @ConditionalOnProperty(name = "yexuejc.redis.db1") public JedisConnectionFactory redisConnectionFactory1() throws UnknownHostException { - return createJedisConnectionFactory(1); + return applyProperties(createJedisConnectionFactory(), 1); } @Bean(BEAN_REDIS_FACTORY2) @ConditionalOnProperty(name = "yexuejc.redis.db2") public JedisConnectionFactory redisConnectionFactory2() throws UnknownHostException { - return createJedisConnectionFactory(2); + return applyProperties(createJedisConnectionFactory(), 2); } @Bean(BEAN_REDIS_FACTORY3) @ConditionalOnProperty(name = "yexuejc.redis.db3") public JedisConnectionFactory redisConnectionFactory3() throws UnknownHostException { - return createJedisConnectionFactory(3); + return applyProperties(createJedisConnectionFactory(), 3); } @Bean(BEAN_REDIS_FACTORY4) @ConditionalOnProperty(name = "yexuejc.redis.db4") public JedisConnectionFactory redisConnectionFactory4() throws UnknownHostException { - return createJedisConnectionFactory(4); + return applyProperties(createJedisConnectionFactory(), 4); } @Bean(BEAN_REDIS_FACTORY5) @ConditionalOnProperty(name = "yexuejc.redis.db5") public JedisConnectionFactory redisConnectionFactory5() throws UnknownHostException { - return createJedisConnectionFactory(5); + return applyProperties(createJedisConnectionFactory(), 5); } @Bean(BEAN_REDIS_FACTORY6) @ConditionalOnProperty(name = "yexuejc.redis.db6") public JedisConnectionFactory redisConnectionFactory6() throws UnknownHostException { - return createJedisConnectionFactory(6); + return applyProperties(createJedisConnectionFactory(), 6); } @Bean(BEAN_REDIS_FACTORY7) @ConditionalOnProperty(name = "yexuejc.redis.db7") public JedisConnectionFactory redisConnectionFactory7() throws UnknownHostException { - return createJedisConnectionFactory(7); + return applyProperties(createJedisConnectionFactory(), 7); } @Bean(BEAN_REDIS_FACTORY8) @ConditionalOnProperty(name = "yexuejc.redis.db8") public JedisConnectionFactory redisConnectionFactory8() throws UnknownHostException { - return createJedisConnectionFactory(8); + return applyProperties(createJedisConnectionFactory(), 8); } @Bean(BEAN_REDIS_FACTORY9) @ConditionalOnProperty(name = "yexuejc.redis.db9") public JedisConnectionFactory redisConnectionFactory9() throws UnknownHostException { - return createJedisConnectionFactory(9); + return applyProperties(createJedisConnectionFactory(), 9); } - private JedisConnectionFactory createJedisConnectionFactory(int database) { - RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); - redisStandaloneConfiguration.setHostName(properties.getHost()); - redisStandaloneConfiguration.setPort(properties.getPort()); - redisStandaloneConfiguration.setDatabase(database); - redisStandaloneConfiguration.setPassword(RedisPassword.of(properties.getPassword())); - - JedisClientConfiguration.JedisClientConfigurationBuilder jedisClientConfiguration = JedisClientConfiguration.builder(); - - JedisConnectionFactory factory = new JedisConnectionFactory(redisStandaloneConfiguration, - jedisClientConfiguration.build()); + protected final JedisConnectionFactory applyProperties(JedisConnectionFactory factory, int database) { + configureConnection(factory); + if (this.properties.isSsl()) { + factory.setUseSsl(true); + } + factory.setDatabase(database); + if (this.properties.getTimeout() > 0) { + factory.setTimeout(this.properties.getTimeout()); + } return factory; } - } + private void configureConnection(JedisConnectionFactory factory) { + if (StringUtils.hasText(this.properties.getUrl())) { + configureConnectionFromUrl(factory); + } else { + factory.setHostName(this.properties.getHost()); + factory.setPort(this.properties.getPort()); + if (this.properties.getPassword() != null) { + factory.setPassword(this.properties.getPassword()); + } + } + } + private void configureConnectionFromUrl(JedisConnectionFactory factory) { + String url = this.properties.getUrl(); + if (url.startsWith("rediss://")) { + factory.setUseSsl(true); + } + try { + URI uri = new URI(url); + factory.setHostName(uri.getHost()); + factory.setPort(uri.getPort()); + if (uri.getUserInfo() != null) { + String password = uri.getUserInfo(); + int index = password.lastIndexOf(":"); + if (index >= 0) { + password = password.substring(index + 1); + } + factory.setPassword(password); + } + } catch (URISyntaxException ex) { + throw new IllegalArgumentException("Malformed 'spring.redis.url' " + url, ex); + } + } + + protected final RedisSentinelConfiguration getSentinelConfig() { + if (this.sentinelConfiguration != null) { + return this.sentinelConfiguration; + } + Sentinel sentinelProperties = this.properties.getSentinel(); + if (sentinelProperties != null) { + RedisSentinelConfiguration config = new RedisSentinelConfiguration(); + config.master(sentinelProperties.getMaster()); + config.setSentinels(createSentinels(sentinelProperties)); + return config; + } + return null; + } + + /** + * Create a {@link RedisClusterConfiguration} if necessary. + * + * @return {@literal null} if no cluster settings are set. + */ + protected final RedisClusterConfiguration getClusterConfiguration() { + if (this.clusterConfiguration != null) { + return this.clusterConfiguration; + } + if (this.properties.getCluster() == null) { + return null; + } + Cluster clusterProperties = this.properties.getCluster(); + RedisClusterConfiguration config = new RedisClusterConfiguration(clusterProperties.getNodes()); + + if (clusterProperties.getMaxRedirects() != null) { + config.setMaxRedirects(clusterProperties.getMaxRedirects()); + } + return config; + } + + private List createSentinels(Sentinel sentinel) { + List nodes = new ArrayList(); + for (String node : StringUtils.commaDelimitedListToStringArray(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; + } + + private JedisConnectionFactory createJedisConnectionFactory() { + JedisPoolConfig poolConfig = this.properties.getPool() != null ? jedisPoolConfig() : new JedisPoolConfig(); + + if (getSentinelConfig() != null) { + return new JedisConnectionFactory(getSentinelConfig(), poolConfig); + } + if (getClusterConfiguration() != null) { + return new JedisConnectionFactory(getClusterConfiguration(), poolConfig); + } + return new JedisConnectionFactory(poolConfig); + } + + private JedisPoolConfig jedisPoolConfig() { + JedisPoolConfig config = new JedisPoolConfig(); + RedisProperties.Pool props = this.properties.getPool(); + config.setMaxTotal(props.getMaxActive()); + config.setMaxIdle(props.getMaxIdle()); + config.setMinIdle(props.getMinIdle()); + config.setMaxWaitMillis(props.getMaxWait()); + return config; + } + + } /** * Standard Redis configuration. @@ -346,4 +471,5 @@ public class MutiRedisAutoConfiguration { } } + } diff --git a/yexuejc-springboot-example/yexuejc-springboot-simple/pom.xml b/yexuejc-springboot-example/yexuejc-springboot-simple/pom.xml index 65145c3..a21bd9a 100644 --- a/yexuejc-springboot-example/yexuejc-springboot-simple/pom.xml +++ b/yexuejc-springboot-example/yexuejc-springboot-simple/pom.xml @@ -21,7 +21,7 @@ com.yexuejc.springboot yexuejc-springboot-base - 1.2.1 + ${project.parent.version} org.springframework.boot