SpringBoot 多 PgSQL 数据源的一种方式

842 字约 3 分钟...

SpringBoot 配置多个 PgSQL 的一种方式。

默认配置文件形式

多数据源最快的做法按照固定格式配置多数据源 yaml 文件。

spring:
    datasource:
        dynamic:
            primary: main
            datasource:
                main:
                    username: admin
                    password: admin
                    url: jdbc:mysql://192.168.2.36:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
                    driver-class-name: com.mysql.cj.jdbc.Driver
                    # 单数据源连接池配置
                    druid:
                        initial-size: 20
                        min-idle: 20
                        max-active: 1000
                        max-wait: 60000
                        query-timeout: 60000
                        validation-query: SELECT 1
                        test-while-idle: true
                        test-on-borrow: false
                        test-on-return: false
                        time-between-eviction-runs-millis: 60000
                        min-evictable-idle-time-millis: 300000
                other1:
                    username: admin
                    password: admin
                    url: jdbc:mysql://192.168.2.37:3306/test2?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
                    driver-class-name: com.mysql.cj.jdbc.Driver
                    # 可继承全局druid配置,也可单独覆盖
                    druid:
                        initial-size: 5
                        min-idle: 5
                        max-active: 100

启动类排除默认配置

@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

最后在方法上通过注解DS就可以实现数据源的切换。

@Repository
@DS("other1")
public interface User2Mapper extends BaseMapper<User2> {
}

自定义配置文件形式

假如我不想按照默认的格式配置数据源信息,比如我就想放在其他地方:

extension:
    model-parse:
        tdimpRelease:
            db: '{"dbName":"test","host":"192.168.2.38","password":"admin","port":5432,"tablePrefix":"dev_","type":"postgresql","username":"postgres"}'

主库还是按照默认的方式进行配置。

首先我们需要一个配置将主数据源打上标签@Primary

/**
 * 主数据源
 */
@Configuration
public class PrimaryDataSourceConfig {

    @Bean(name = "dataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return new DruidDataSource();
    }

    @Bean(name = "jdbcTemplate")
    @Primary
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource());
    }
}

然后配置我们的自定义数据源,同样增加一个配置文件。

@Configuration
@ConditionalOnProperty(
        name = "extension.model-parse.tdimpRelease.enable",
        havingValue = "true"
)
public class ReleasePgDataSourceConfig {
    private static final Logger logger = LoggerFactory.getLogger(ReleasePgDataSourceConfig.class);

    public static final String TEMPLATE = "releasePgJdbcTemplate";

    @Value("${extension.model-parse.tdimpRelease.db:0}")
    private String dbConfig;


    @Bean(name = "releasePgDataSource")
    public DataSource releasePgDataSource() {
        JSONObject entries = JSONUtil.parseObj(dbConfig);
        DruidDataSource ds = new DruidDataSource();
        ds.setName("releasePgDataSource");
        // ===== 基本连接信息 =====
        ds.setUrl(String.format("jdbc:postgresql://%s:%d/%s"
                , entries.getStr("host")
                , entries.getInt("port")
                , entries.getStr("dbName"))
        );
        ds.setUsername(entries.getStr("username"));
        ds.setPassword(entries.getStr("password"));
        ds.setDriverClassName("org.postgresql.Driver");
        // ===== 连接池参数 =====
        ds.setInitialSize(10);
        ds.setMinIdle(10);
        ds.setMaxActive(50);
        ds.setMaxWait(60000);
        // ===== 连接校验 =====
        ds.setValidationQuery("SELECT 1");
        ds.setTestWhileIdle(true);
        ds.setTestOnBorrow(false);
        ds.setTestOnReturn(false);
        // ===== 空闲连接回收 =====
        ds.setTimeBetweenEvictionRunsMillis(60000);
        ds.setMinEvictableIdleTimeMillis(300000);
        // ===== Druid 监控 =====
        try {
            ds.setFilters("stat,wall,slf4j");
        } catch (SQLException e) {
            logger.error("配置release pg druid监控失败!");
        }
        ds.setAsyncInit(false);
        try {
            ds.init();
        } catch (SQLException e) {
            logger.error("注册发布数据库连接池失败!发布数据库信息:{}", dbConfig, e);
        }
        return ds;
    }

    @Bean(name = "releasePgJdbcTemplate")
    public JdbcTemplate releasePgJdbcTemplate() {
        return new JdbcTemplate(releasePgDataSource());
    }
}

这个时候服务启动,就会注册多个数据源。可以做个单元测试。

@ActiveProfiles("t-dev")
@SpringBootTest()
public class ReleasePgJdbcTemplateTest extends BaseTest {
    private static final Logger logger = LoggerFactory.getLogger(ReleasePgJdbcTemplateTest.class);

    @Resource
    @Qualifier("releasePgJdbcTemplate")
    private JdbcTemplate releasePgJdbcTemplate;

    @Test
    public void testQuery() {
        List<Object> query = releasePgJdbcTemplate.query(
                "select * from test limit 1",
                new BeanPropertyRowMapper<>(Object.class)
        );
        logger.info("list:{}", JSONUtil.toJsonPrettyStr(query));
    }
}

将连接池加入到监控页面。

修改主数据源配置文件,增加配置, 开启监控页面。

  @Bean
  public ServletRegistrationBean<StatViewServlet> statViewServlet() {
      ServletRegistrationBean<StatViewServlet> bean =
              new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
      bean.addInitParameter("loginUsername", "admin");
      bean.addInitParameter("loginPassword", "admin");
      bean.addInitParameter("allow", "");
      bean.addInitParameter("resetEnable", "false");
      return bean;
  }

然后将自定义数据源加入到监控页面。修改自定义数据源配置文件。

@Bean(name = "releasePgJdbcTemplate")
public JdbcTemplate releasePgJdbcTemplate() {
    DataSource dataSource = releasePgDataSource();
    // ========== 将自定义数据源注册到 Druid 监控 ==========
    DruidDataSourceStatManager.addDataSource(dataSource, "releasePgDataSource");
    logger.info("✅已经初始化发布Pgsql客户端!");
    return new JdbcTemplate(dataSource);
}

打开监控页面:ip:port/druid

SpringBoot多PgSQL数据源的一种方式

这种配置方式好处就是完全不影响主库的使用,如果后期增加数据源,按照配置再复制一个就行了。

缺点就是需要使用 JdbcTemplate 去操作数据库了。

💬 评论区