From e7f0814d7d9f31b8da85412e5e1d372f6245f607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=AE=89=E5=AE=B6?= Date: Mon, 17 Aug 2020 19:30:25 +0800 Subject: [PATCH] feat(starter): support spring config server/appolo/nacos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit support spring config server/appolo/nacos compatible spring boot's config (`spring.redis.redisson.config=classpath:redisson.yaml`) Closes issues#2918 Closes issues#2765 Closes issues#2086 Closes issues#1829 Signed-off-by: 赵安家 --- redisson-spring-boot-starter/README.md | 67 +++++++--- .../starter/RedissonAutoConfiguration.java | 115 ++++++++++-------- .../spring/starter/RedissonProperties.java | 24 +++- 3 files changed, 133 insertions(+), 73 deletions(-) diff --git a/redisson-spring-boot-starter/README.md b/redisson-spring-boot-starter/README.md index 2d8f993ce..10669241e 100644 --- a/redisson-spring-boot-starter/README.md +++ b/redisson-spring-boot-starter/README.md @@ -43,23 +43,62 @@ Downgrade `redisson-spring-data` module if necessary to support required Spring Common spring boot settings or Redisson settings could be used. -```properties +```yaml # common spring boot settings -spring.redis.database= -spring.redis.host= -spring.redis.port= -spring.redis.password= -spring.redis.ssl= -spring.redis.timeout= -spring.redis.cluster.nodes= -spring.redis.sentinel.master= -spring.redis.sentinel.nodes= +spring: + redis: + database: + host: + port: + password: + ssl: + timeout: + cluster: + nodes: + sentinel: + master: + nodes: + + # Redisson settings + + #path to config - redisson.yaml + redisson: + config: classpath:redisson.yaml + configBlock: | + clusterServersConfig: + idleConnectionTimeout: 10000 + connectTimeout: 10000 + timeout: 3000 + retryAttempts: 3 + retryInterval: 1500 + failedSlaveReconnectionInterval: 3000 + failedSlaveCheckInterval: 60000 + password: null + subscriptionsPerConnection: 5 + clientName: null + loadBalancer: ! {} + subscriptionConnectionMinimumIdleSize: 1 + subscriptionConnectionPoolSize: 50 + slaveConnectionMinimumIdleSize: 24 + slaveConnectionPoolSize: 64 + masterConnectionMinimumIdleSize: 24 + masterConnectionPoolSize: 64 + readMode: "SLAVE" + subscriptionMode: "SLAVE" + nodeAddresses: + - "redis://127.0.0.1:7004" + - "redis://127.0.0.1:7001" + - "redis://127.0.0.1:7000" + scanInterval: 1000 + pingConnectionInterval: 0 + keepAlive: false + tcpNoDelay: false + threads: 16 + nettyThreads: 32 + codec: ! {} + transportMode: "NIO" -# Redisson settings - -#path to config - redisson.yaml -spring.redis.redisson.config=classpath:redisson.yaml ``` ### 3. Use Redisson through spring bean with `RedissonClient` interface or `RedisTemplate`/`ReactiveRedisTemplate` objects diff --git a/redisson-spring-boot-starter/src/main/java/org/redisson/spring/starter/RedissonAutoConfiguration.java b/redisson-spring-boot-starter/src/main/java/org/redisson/spring/starter/RedissonAutoConfiguration.java index af56fba7d..781f62bad 100644 --- a/redisson-spring-boot-starter/src/main/java/org/redisson/spring/starter/RedissonAutoConfiguration.java +++ b/redisson-spring-boot-starter/src/main/java/org/redisson/spring/starter/RedissonAutoConfiguration.java @@ -1,12 +1,12 @@ /** * Copyright (c) 2013-2020 Nikita Koksharov - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,13 +15,6 @@ */ package org.redisson.spring.starter; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; @@ -44,11 +37,16 @@ import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.util.ReflectionUtils; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** - * * @author Nikita Koksharov * @author Nikos Kakavas (https://github.com/nikakis) - * */ @Configuration @ConditionalOnClass({Redisson.class, RedisOperations.class}) @@ -56,18 +54,21 @@ import org.springframework.util.ReflectionUtils; @EnableConfigurationProperties({RedissonProperties.class, RedisProperties.class}) public class RedissonAutoConfiguration { + private static final String REDIS_PROTOCOL_PREFIX = "redis://"; + private static final String REDISS_PROTOCOL_PREFIX = "rediss://"; + @Autowired(required = false) private List redissonAutoConfigurationCustomizers; @Autowired private RedissonProperties redissonProperties; - + @Autowired private RedisProperties redisProperties; - + @Autowired private ApplicationContext ctx; - + @Bean @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { @@ -89,33 +90,42 @@ public class RedissonAutoConfiguration { public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) { return new RedissonConnectionFactory(redisson); } - + @Bean(destroyMethod = "shutdown") @ConditionalOnMissingBean(RedissonClient.class) public RedissonClient redisson() throws IOException { - Config config = null; + Config config; Method clusterMethod = ReflectionUtils.findMethod(RedisProperties.class, "getCluster"); Method timeoutMethod = ReflectionUtils.findMethod(RedisProperties.class, "getTimeout"); Object timeoutValue = ReflectionUtils.invokeMethod(timeoutMethod, redisProperties); int timeout; - if(null == timeoutValue){ + if (null == timeoutValue) { timeout = 10000; - }else if (!(timeoutValue instanceof Integer)) { + } else if (!(timeoutValue instanceof Integer)) { Method millisMethod = ReflectionUtils.findMethod(timeoutValue.getClass(), "toMillis"); timeout = ((Long) ReflectionUtils.invokeMethod(millisMethod, timeoutValue)).intValue(); } else { - timeout = (Integer)timeoutValue; + timeout = (Integer) timeoutValue; } - - if (redissonProperties.getConfig() != null) { + if (redissonProperties.getConfigBlock() != null) { + try { + config = Config.fromYAML(redissonProperties.getConfigBlock()); + } catch (IOException e) { + try { + config = Config.fromJSON(redissonProperties.getConfigBlock()); + } catch (IOException e1) { + throw new IllegalArgumentException("Can't parse config", e1); + } + } + } else if (redissonProperties.getConfig() != null) { try { InputStream is = getConfigStream(); - config = Config.fromJSON(is); + config = Config.fromYAML(is); } catch (IOException e) { // trying next format try { InputStream is = getConfigStream(); - config = Config.fromYAML(is); + config = Config.fromJSON(is); } catch (IOException e1) { throw new IllegalArgumentException("Can't parse config", e1); } @@ -123,46 +133,46 @@ public class RedissonAutoConfiguration { } else if (redisProperties.getSentinel() != null) { Method nodesMethod = ReflectionUtils.findMethod(Sentinel.class, "getNodes"); Object nodesValue = ReflectionUtils.invokeMethod(nodesMethod, redisProperties.getSentinel()); - + String[] nodes; if (nodesValue instanceof String) { - nodes = convert(Arrays.asList(((String)nodesValue).split(","))); + nodes = convert(Arrays.asList(((String) nodesValue).split(","))); } else { - nodes = convert((List)nodesValue); + nodes = convert((List) nodesValue); } - + config = new Config(); config.useSentinelServers() - .setMasterName(redisProperties.getSentinel().getMaster()) - .addSentinelAddress(nodes) - .setDatabase(redisProperties.getDatabase()) - .setConnectTimeout(timeout) - .setPassword(redisProperties.getPassword()); + .setMasterName(redisProperties.getSentinel().getMaster()) + .addSentinelAddress(nodes) + .setDatabase(redisProperties.getDatabase()) + .setConnectTimeout(timeout) + .setPassword(redisProperties.getPassword()); } else if (clusterMethod != null && ReflectionUtils.invokeMethod(clusterMethod, redisProperties) != null) { Object clusterObject = ReflectionUtils.invokeMethod(clusterMethod, redisProperties); Method nodesMethod = ReflectionUtils.findMethod(clusterObject.getClass(), "getNodes"); List nodesObject = (List) ReflectionUtils.invokeMethod(nodesMethod, clusterObject); - + String[] nodes = convert(nodesObject); - + config = new Config(); config.useClusterServers() - .addNodeAddress(nodes) - .setConnectTimeout(timeout) - .setPassword(redisProperties.getPassword()); + .addNodeAddress(nodes) + .setConnectTimeout(timeout) + .setPassword(redisProperties.getPassword()); } else { config = new Config(); - String prefix = "redis://"; + String prefix = REDIS_PROTOCOL_PREFIX; Method method = ReflectionUtils.findMethod(RedisProperties.class, "isSsl"); - if (method != null && (Boolean)ReflectionUtils.invokeMethod(method, redisProperties)) { - prefix = "rediss://"; + if (method != null && (Boolean) ReflectionUtils.invokeMethod(method, redisProperties)) { + prefix = REDISS_PROTOCOL_PREFIX; } - + config.useSingleServer() - .setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort()) - .setConnectTimeout(timeout) - .setDatabase(redisProperties.getDatabase()) - .setPassword(redisProperties.getPassword()); + .setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort()) + .setConnectTimeout(timeout) + .setDatabase(redisProperties.getDatabase()) + .setPassword(redisProperties.getPassword()); } if (redissonAutoConfigurationCustomizers != null) { for (RedissonAutoConfigurationCustomizer customizer : redissonAutoConfigurationCustomizers) { @@ -175,20 +185,19 @@ public class RedissonAutoConfiguration { private String[] convert(List nodesObject) { List nodes = new ArrayList(nodesObject.size()); for (String node : nodesObject) { - if (!node.startsWith("redis://") && !node.startsWith("rediss://")) { - nodes.add("redis://" + node); + if (!node.startsWith(REDIS_PROTOCOL_PREFIX) && !node.startsWith(REDISS_PROTOCOL_PREFIX)) { + nodes.add(REDIS_PROTOCOL_PREFIX + node); } else { nodes.add(node); } } - return nodes.toArray(new String[nodes.size()]); + return nodes.toArray(new String[0]); } private InputStream getConfigStream() throws IOException { Resource resource = ctx.getResource(redissonProperties.getConfig()); - InputStream is = resource.getInputStream(); - return is; + return resource.getInputStream(); } - + } diff --git a/redisson-spring-boot-starter/src/main/java/org/redisson/spring/starter/RedissonProperties.java b/redisson-spring-boot-starter/src/main/java/org/redisson/spring/starter/RedissonProperties.java index 89604e976..7d081f4b7 100644 --- a/redisson-spring-boot-starter/src/main/java/org/redisson/spring/starter/RedissonProperties.java +++ b/redisson-spring-boot-starter/src/main/java/org/redisson/spring/starter/RedissonProperties.java @@ -1,12 +1,12 @@ /** * Copyright (c) 2013-2020 Nikita Koksharov - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,8 +18,9 @@ package org.redisson.spring.starter; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * + * * @author Nikita Koksharov + * @author AnJia (https://anjia0532.github.io/) * */ @ConfigurationProperties(prefix = "spring.redis.redisson") @@ -27,6 +28,8 @@ public class RedissonProperties { private String config; + private String configBlock; + public String getConfig() { return config; } @@ -34,5 +37,14 @@ public class RedissonProperties { public void setConfig(String config) { this.config = config; } - + + public String getConfigBlock() { + return configBlock; + } + + public void setConfigBlock(String configBlock) { + this.configBlock = configBlock; + } + + }