springboot链接redis IPV6

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
package org.springframework.boot.autoconfigure.data.redis;

/**
 * 解决Jredis配置文件,不兼容IPV6地址的BUG
 */
@Slf4j
@Configuration
@ConditionalOnClass({GenericObjectPool.class, JedisConnection.class, Jedis.class})
@AutoConfigureOrder(value = Ordered.HIGHEST_PRECEDENCE)
public class MsfJedisConnectionConfiguration extends RedisConnectionConfiguration {

    private final RedisProperties properties;

    public MsfJedisConnectionConfiguration(RedisProperties properties,
                                           ObjectProvider<RedisSentinelConfiguration> sentinelConfiguration,
                                           ObjectProvider<RedisClusterConfiguration> clusterConfiguration) {
        super(properties, sentinelConfiguration, clusterConfiguration);
        this.properties = properties;
    }

    @Bean
    public JedisConnectionFactory redisConnectionFactory(
            ObjectProvider<JedisClientConfigurationBuilderCustomizer> builderCustomizers) throws UnknownHostException {
        return createJedisConnectionFactory(builderCustomizers);
    }

    private JedisConnectionFactory createJedisConnectionFactory(
            ObjectProvider<JedisClientConfigurationBuilderCustomizer> builderCustomizers) {
        JedisClientConfiguration clientConfiguration = getJedisClientConfiguration(builderCustomizers);
        if (getSentinelConfig() != null) {
            return new JedisConnectionFactory(getSentinelConfig(), clientConfiguration);
        }
        RedisClusterConfiguration redisClusterConfiguration = getClusterConfiguration1();
        if (redisClusterConfiguration != null) {
            Set<RedisNode> nodes=redisClusterConfiguration.getClusterNodes();
            log.info("clusterNodes:{}",nodes);
            log.info("password:{}",redisClusterConfiguration.getPassword());
            log.info("maxRedirects:{}",redisClusterConfiguration.getMaxRedirects());
            return new JedisConnectionFactory(redisClusterConfiguration, clientConfiguration);
        }
        return new JedisConnectionFactory(getStandaloneConfig(), clientConfiguration);
    }


    /**
     * Create a {@link RedisClusterConfiguration} if necessary.
     *
     * @return {@literal null} if no cluster settings are set.
     */
    protected final RedisClusterConfiguration getClusterConfiguration1() {
        if (properties == null) {
            return null;
        }
        RedisProperties.Cluster clusterProperties = properties.getCluster();
        if (clusterProperties != null) {
            MsfRedisClusterConfiguration config = new MsfRedisClusterConfiguration(clusterProperties.getNodes());
            if (clusterProperties.getMaxRedirects() != null) {
                config.setMaxRedirects(clusterProperties.getMaxRedirects());
            }
            if (properties.getPassword() != null) {
                config.setPassword(RedisPassword.of(properties.getPassword()));
            }
            return config;
        } else {
            return null;
        }
    }


    private JedisClientConfiguration getJedisClientConfiguration(
            ObjectProvider<JedisClientConfigurationBuilderCustomizer> builderCustomizers) {
        JedisClientConfigurationBuilder builder = applyProperties(JedisClientConfiguration.builder());
        RedisProperties.Pool pool = properties.getJedis().getPool();
        if (pool != null) {
            applyPooling(pool, builder);
        }
        if (StringUtils.hasText(properties.getUrl())) {
            customizeConfigurationFromUrl(builder);
        }
        builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
        return builder.build();
    }

    private JedisClientConfigurationBuilder applyProperties(JedisClientConfigurationBuilder builder) {
        if (properties.isSsl()) {
            builder.useSsl();
        }
        if (properties.getTimeout() != null) {
            Duration timeout = properties.getTimeout();
            builder.readTimeout(timeout).connectTimeout(timeout);
        }
        return builder;
    }

    private void applyPooling(RedisProperties.Pool pool,
                              JedisClientConfiguration.JedisClientConfigurationBuilder builder) {
        builder.usePooling().poolConfig(jedisPoolConfig(pool));
    }

    private JedisPoolConfig jedisPoolConfig(RedisProperties.Pool pool) {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(pool.getMaxActive());
        config.setMaxIdle(pool.getMaxIdle());
        config.setMinIdle(pool.getMinIdle());
        if (pool.getMaxWait() != null) {
            config.setMaxWaitMillis(pool.getMaxWait().toMillis());
        }
        return config;
    }

    private void customizeConfigurationFromUrl(JedisClientConfiguration.JedisClientConfigurationBuilder builder) {
        ConnectionInfo connectionInfo = parseUrl(properties.getUrl());
        if (connectionInfo.isUseSsl()) {
            builder.useSsl();
        }
    }

}
package org.springframework.boot.autoconfigure.data.redis;
/**
 * MsfRedisClusterConfiguration 
 */
@Slf4j
public class MsfRedisClusterConfiguration extends RedisClusterConfiguration {

    private static final String REDIS_CLUSTER_NODES_CONFIG_PROPERTY = "spring.redis.cluster.nodes";
    private static final String REDIS_CLUSTER_MAX_REDIRECTS_CONFIG_PROPERTY = "spring.redis.cluster.max-redirects";
    private Set<RedisNode> clusterNodes = new HashSet<>();

    public MsfRedisClusterConfiguration() {
    }

    public MsfRedisClusterConfiguration(Collection<String> clusterNodes) {
        this(new MapPropertySource("RedisClusterConfiguration", asMap(clusterNodes, -1)));
    }

    public MsfRedisClusterConfiguration(PropertySource<?> propertySource) {
        notNull(propertySource, "PropertySource must not be null!");

        this.clusterNodes = new HashSet<>();

        if (propertySource.containsProperty(REDIS_CLUSTER_NODES_CONFIG_PROPERTY)) {
            appendClusterNodes(
                    commaDelimitedListToSet(propertySource.getProperty(REDIS_CLUSTER_NODES_CONFIG_PROPERTY).toString()));
        }
        if (propertySource.containsProperty(REDIS_CLUSTER_MAX_REDIRECTS_CONFIG_PROPERTY)) {
            this.setMaxRedirects(NumberUtils.parseNumber(
                    propertySource.getProperty(REDIS_CLUSTER_MAX_REDIRECTS_CONFIG_PROPERTY).toString(), Integer.class));
        }
    }

    /**
     * 重写父类解析IP地址和端口号的代码,兼容IPV6地址
     *
     * @param node
     * @return
     */
    private RedisNode readHostAndPortFromString(String node) {

//		String[] args = split(hostAndPort, ":");
//
//		notNull(args, "HostAndPort need to be seperated by  ':'.");
//		isTrue(args.length == 2, "Host and Port String needs to specified as host:port");
//		return new RedisNode(args[0], Integer.valueOf(args[1]));

        HostAndPort hostAndPort = HostAndPort.fromString(node);
        String host = hostAndPort.getHostText();
        int port = hostAndPort.getPort();
        return new RedisNode(host, port);
    }

    /**
     * @param clusterHostAndPorts must not be {@literal null} or empty.
     * @param redirects           the max number of redirects to follow.
     * @return cluster config map with properties.
     */
    private static Map<String, Object> asMap(Collection<String> clusterHostAndPorts, int redirects) {

        notNull(clusterHostAndPorts, "ClusterHostAndPorts must not be null!");

        Map<String, Object> map = new HashMap<>();
        map.put(REDIS_CLUSTER_NODES_CONFIG_PROPERTY, StringUtils.collectionToCommaDelimitedString(clusterHostAndPorts));

        if (redirects >= 0) {
            map.put(REDIS_CLUSTER_MAX_REDIRECTS_CONFIG_PROPERTY, redirects);
        }

        return map;
    }

    protected void appendClusterNodes(Set<String> hostAndPorts) {

        for (String hostAndPort : hostAndPorts) {
            addClusterNodeCustomer(readHostAndPortFromString(hostAndPort));
        }
        this.setClusterNodes(this.clusterNodes);
    }


    /**
     * Add a cluster node to configuration.
     *
     * @param node must not be {@literal null}.
     */
    public void addClusterNodeCustomer(RedisNode node) {
        notNull(node, "ClusterNode must not be 'null'.");
        this.clusterNodes.add(node);
    }

}
/**
 * RedisConfig
 */
@Configuration
@Import({MsfJedisConnectionConfiguration.class, MsfRedisClusterConfiguration.class})
public class RedisConfig {
}

posted @ 2024-04-26 15:46  呀啦嗦  阅读(74)  评论(0编辑  收藏  举报