sharding-jdbc 5.5.1 从nacos读取配置文件

581 阅读1分钟

由于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的官方文档}