From 24d1b3ca9416d7b56454bedf33e9aeab70cd5be3 Mon Sep 17 00:00:00 2001 From: Yanming Zhou Date: Tue, 14 Jan 2025 16:42:55 +0800 Subject: [PATCH] Parse redis database from url if present See gh-43813 Signed-off-by: Yanming Zhou --- .../PropertiesRedisConnectionDetails.java | 6 +++-- .../redis/RedisConnectionConfiguration.java | 20 ++++++++++++++-- .../data/redis/RedisProperties.java | 5 ++-- ...PropertiesRedisConnectionDetailsTests.java | 24 +++++++++++++++++++ 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/PropertiesRedisConnectionDetails.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/PropertiesRedisConnectionDetails.java index 18371b3200fd..b06da68040fa 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/PropertiesRedisConnectionDetails.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/PropertiesRedisConnectionDetails.java @@ -27,6 +27,7 @@ * @author Andy Wilkinson * @author Phillip Webb * @author Scott Frederick + * @author Yanming Zhou */ class PropertiesRedisConnectionDetails implements RedisConnectionDetails { @@ -59,7 +60,8 @@ public Standalone getStandalone() { if (this.properties.getUrl() != null) { ConnectionInfo connectionInfo = ConnectionInfo.of(this.properties.getUrl()); return Standalone.of(connectionInfo.getUri().getHost(), connectionInfo.getUri().getPort(), - this.properties.getDatabase()); + (connectionInfo.getDatabase() != null) ? connectionInfo.getDatabase() + : this.properties.getDatabase()); } return Standalone.of(this.properties.getHost(), this.properties.getPort(), this.properties.getDatabase()); } @@ -75,7 +77,7 @@ public Sentinel getSentinel() { @Override public int getDatabase() { - return PropertiesRedisConnectionDetails.this.properties.getDatabase(); + return getStandalone().getDatabase(); } @Override diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisConnectionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisConnectionConfiguration.java index 4b19d54550b4..035377ce7319 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisConnectionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisConnectionConfiguration.java @@ -33,6 +33,7 @@ import org.springframework.data.redis.connection.RedisSentinelConfiguration; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; /** * Base Redis connection configuration. @@ -45,6 +46,7 @@ * @author Moritz Halbritter * @author Andy Wilkinson * @author Phillip Webb + * @author Yanming Zhou */ abstract class RedisConnectionConfiguration { @@ -189,11 +191,14 @@ static final class ConnectionInfo { private final String password; - private ConnectionInfo(URI uri, boolean useSsl, String username, String password) { + private final Integer database; + + private ConnectionInfo(URI uri, boolean useSsl, String username, String password, Integer database) { this.uri = uri; this.useSsl = useSsl; this.username = username; this.password = password; + this.database = database; } URI getUri() { @@ -212,6 +217,10 @@ String getPassword() { return this.password; } + Integer getDatabase() { + return this.database; + } + static ConnectionInfo of(String url) { try { URI uri = new URI(url); @@ -233,7 +242,14 @@ static ConnectionInfo of(String url) { password = candidate; } } - return new ConnectionInfo(uri, useSsl, username, password); + Integer database = null; + if (StringUtils.hasText(uri.getPath())) { + String[] pathSplit = uri.getPath().split("/", 2); + if (pathSplit.length > 1 && !pathSplit[1].isEmpty()) { + database = Integer.parseInt(pathSplit[1]); + } + } + return new ConnectionInfo(uri, useSsl, username, password, database); } catch (URISyntaxException ex) { throw new RedisUrlSyntaxException(url, ex); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisProperties.java index 27b0f54a4b76..6fbd7cba4048 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisProperties.java @@ -31,6 +31,7 @@ * @author Mark Paluch * @author Stephane Nicoll * @author Scott Frederick + * @author Yanming Zhou * @since 1.0.0 */ @ConfigurationProperties(prefix = "spring.data.redis") @@ -42,8 +43,8 @@ public class RedisProperties { private int database = 0; /** - * Connection URL. Overrides host, port, username, and password. Example: - * redis://user:password@example.com:6379 + * Connection URL. Overrides host, port, username, password, and database. Example: + * redis://user:password@example.com:6379/8 */ private String url; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/PropertiesRedisConnectionDetailsTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/PropertiesRedisConnectionDetailsTests.java index 4d3aa55ab84f..064cae967d5f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/PropertiesRedisConnectionDetailsTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/PropertiesRedisConnectionDetailsTests.java @@ -103,6 +103,17 @@ void standaloneIsConfiguredFromUrl() { RedisConnectionDetails.Standalone standalone = connectionDetails.getStandalone(); assertThat(standalone.getHost()).isEqualTo("example.com"); assertThat(standalone.getPort()).isEqualTo(1234); + assertThat(standalone.getDatabase()).isEqualTo(9999); + } + + @Test + void standaloneIsConfiguredFromUrlWithoutDatabase() { + this.properties.setUrl("redis://example.com:1234"); + this.properties.setDatabase(5); + PropertiesRedisConnectionDetails connectionDetails = new PropertiesRedisConnectionDetails(this.properties); + RedisConnectionDetails.Standalone standalone = connectionDetails.getStandalone(); + assertThat(standalone.getHost()).isEqualTo("example.com"); + assertThat(standalone.getPort()).isEqualTo(1234); assertThat(standalone.getDatabase()).isEqualTo(5); } @@ -133,9 +144,22 @@ void sentinelIsConfigured() { RedisProperties.Sentinel sentinel = new RedisProperties.Sentinel(); sentinel.setNodes(List.of("localhost:1111", "127.0.0.1:2222", "[::1]:3333")); this.properties.setSentinel(sentinel); + this.properties.setDatabase(5); PropertiesRedisConnectionDetails connectionDetails = new PropertiesRedisConnectionDetails(this.properties); assertThat(connectionDetails.getSentinel().getNodes()).containsExactly(new Node("localhost", 1111), new Node("127.0.0.1", 2222), new Node("[::1]", 3333)); + assertThat(connectionDetails.getSentinel().getDatabase()).isEqualTo(5); + } + + @Test + void sentinelDatabaseIsConfiguredFromUrl() { + RedisProperties.Sentinel sentinel = new RedisProperties.Sentinel(); + sentinel.setNodes(List.of("localhost:1111", "127.0.0.1:2222", "[::1]:3333")); + this.properties.setSentinel(sentinel); + this.properties.setUrl("redis://example.com:1234/9999"); + this.properties.setDatabase(5); + PropertiesRedisConnectionDetails connectionDetails = new PropertiesRedisConnectionDetails(this.properties); + assertThat(connectionDetails.getSentinel().getDatabase()).isEqualTo(9999); } }