由于sharding-jdbc 5.5.1最新版本不再支持springboot的starter包,实际生产配置管理都用的nacos,需要通过自己javaConfig的方式实现从nacos读取配置。
springboot2.4.13 nacos2.1
直接上代码
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.driver.api.yaml.YamlShardingSphereDataSourceFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import javax.sql.DataSource;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Configuration
@Slf4j
public class ShardingConfig {
@Value("${nacos.config.server-addr}")
private String nacosServer;
@Value("${nacos.config.namespace}")
private String nacosNamespace;
@Value("${nacos.config.username}")
private String nacosUsername;
@Value("${nacos.config.password}")
private String nacosPassword;
@Value("${sharding.nacos.config.data-id}")
private String nacosDataId;
@Value("${sharding.nacos.config.group-id}")
private String nacosGroupId;
@Autowired
private Environment env;
private static final String KEY_VALUE_SEPARATOR = "::";
private static final Pattern PATTERN = Pattern.compile("\$\$\{(.+::.*)}$");
@Bean
public DataSource createDataSource() throws SQLException, IOException {
return YamlShardingSphereDataSourceFactory.createDataSource(getYamlContent());
}
/**
* 从nacos配置中心获取yml文件
* PS: sharding-jdbc的yml文件value替换环境变量的标识符为$${::} example: env.url=exampleValue 在yml中$${env.url::} 将替换为 exampleValue
* @return
*/
private byte[] getYamlContent() {
Properties properties = new Properties();
properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosServer);
properties.setProperty(PropertyKeyConst.USERNAME, nacosUsername);
properties.setProperty(PropertyKeyConst.PASSWORD, nacosPassword);
properties.setProperty(PropertyKeyConst.NAMESPACE, nacosNamespace);
try {
ConfigService configService = NacosFactory.createConfigService(properties);
String content = configService.getConfig(nacosDataId, nacosGroupId, 6000);
byte[] ymlConfigBytes = replaceEnvConfig(content.getBytes());
log.info("load sharding-config successfully");
if (log.isDebugEnabled()) {
log.debug(new String(ymlConfigBytes, StandardCharsets.UTF_8));
}
return ymlConfigBytes;
} catch (NacosException e) {
log.error("load sharding-config fail");
throw new RuntimeException(e);
}
}
/**
* 替换yaml文件中定义的环境变量 参考了sharding-jdbc的源码替换方式
* @return
*/
@SneakyThrows(IOException.class)
private byte[] replaceEnvConfig(final byte[] originContent) {
try (InputStream stream = new ByteArrayInputStream(originContent);
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
StringBuilder builder = new StringBuilder();
String line;
while (null != (line = reader.readLine())) {
if (!line.startsWith("#")) {
line = replaceEnvironmentVariables(line);
builder.append(line).append('\n');
}
}
return builder.toString().getBytes(StandardCharsets.UTF_8);
}
}
private String replaceEnvironmentVariables(final String line) {
Matcher matcher = PATTERN.matcher(line);
if (!matcher.find()) {
return line;
}
String[] envNameAndDefaultValue = matcher.group(1).split(KEY_VALUE_SEPARATOR, 2);
String envName = envNameAndDefaultValue[0];
String envValue = getEnvironmentVariables(envName);
if (!StringUtils.hasText(envValue) && envNameAndDefaultValue[1].isEmpty()) {
String modifiedLineWithSpace = matcher.replaceAll("");
return modifiedLineWithSpace.substring(0, modifiedLineWithSpace.length() - 1);
}
if (!StringUtils.hasText(envValue)) {
envValue = envNameAndDefaultValue[1];
}
return matcher.replaceAll(envValue);
}
/**
* 此处从spring上下文的环境变量中获取配置(含spring配置文件+naocs配置+系统环境变量)
*
* @param name
* @return
*/
private String getEnvironmentVariables(final String name) {
return env.getProperty(name);
}
}
在springboot的配置文件application.properties-{env}中配上对应的nacos的配置信息。
最后再参照sharding-jdbc的官方文档配置yml文件到nacos中即可。{yml默认支持springboot的配置以及环境变量替换, 表达式可以参考上方注释或者sharding-jdbc的官方文档}