添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
文武双全的足球  ·  Working with ...·  1 年前    · 
会搭讪的石榴  ·  LCPK003I Open of ...·  2 年前    · 

SpringBoot整合Druid实现多数据源和可视化监控

先献上 github 代码地址: https://github.com/yudiandemingzi/spring-boot-many-data-source
代码拉下来换下自己的mysql数据库地址,就可以直接运行。Druid的优点很明显,它的可视化界面可以监控Sql语句和URI执行情况在开发中真的很需要。
先说优点吧:

    1) 替换DBCP和C3P0。Druid提供了一个高效、功能强大、可扩展性好的数据库连接池。
    2) 数据库密码加密。直接把数据库密码写在配置文件中,这是不好的行为,容易导致安全问题。
    3) 可以监控数据库访问性能,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能有帮助。
    4) SQL执行日志,Druid提供了不同的LogFilter,监控你应用的数据库   访问情况。
    5)扩展JDBC,如果你要对JDBC层有编程的需求,可以通过Druid提供的Filter-Chain机制,很方便编写JDBC层的扩展插件。

二、配置多数据源

1、pom.xml

只需要添加druid这一个jar就行了,有关springboot项目他还有个整合包,用那个整合包也一样。

       <!-- Druid 数据连接池依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.8</version>
        </dependency>
        <dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-starter</artifactId>
			<version>1.1.6</version>
		</dependency>

对于springboot项目来讲,上面任选一个都是可以的,亲测有效。

2、application.yml

我这里是采用application.yml进行添加配置,这里面配置了两个数据源,其实在application.yml也可以不配置这些东西,它的主要作用是给数据源配置类读取数据用的。

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    initialSize: 10
    minIdle: 10
    maxActive: 200
    # 配置获取连接等待超时的时间
    maxWait: 60000
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 60000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 30000
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    # 打开PSCache,并且指定每个连接上PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    # 配置监控统计拦截的filters
    filters: stat,wall,slf4j
    # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
#配置了两个数据源
master:
  datasource:
    url: jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
    username: root
    password: root
    driverClassName: com.mysql.jdbc.Driver
cluster:
  datasource:
    url: jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
    username: root
    password: root
    driverClassName: com.mysql.jdbc.Driver

3、主数据源配置类(MasterDataSourceConfig)

* 主数据源配置 @Configuration @MapperScan(basePackages = MasterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "masterSqlSessionFactory") public class MasterDataSourceConfig { * 配置多数据源 关键就在这里 这里配置了不同的数据源扫描不同mapper static final String PACKAGE = "com.binron.multidatasource.mapper.master"; static final String MAPPER_LOCATION = "classpath:mapper/master/*.xml"; * 连接数据库信息 这个其实更好的是用配置中心完成 @Value("${master.datasource.url}") private String url; @Value("${master.datasource.username}") private String username; @Value("${master.datasource.password}") private String password; @Value("${master.datasource.driverClassName}") private String driverClassName; * 下面的配置信息可以读取配置文件,其实可以直接写死 如果是多数据源的话 还是考虑读取配置文件 @Value("${spring.datasource.initialSize}") private int initialSize; @Value("${spring.datasource.minIdle}") private int minIdle; @Value("${spring.datasource.maxActive}") private int maxActive; @Value("${spring.datasource.maxWait}") private int maxWait; @Value("${spring.datasource.timeBetweenEvictionRunsMillis}") private int timeBetweenEvictionRunsMillis; @Value("${spring.datasource.minEvictableIdleTimeMillis}") private int minEvictableIdleTimeMillis; @Value("${spring.datasource.validationQuery}") private String validationQuery; @Value("${spring.datasource.testWhileIdle}") private boolean testWhileIdle; @Value("${spring.datasource.testOnBorrow}") private boolean testOnBorrow; @Value("${spring.datasource.testOnReturn}") private boolean testOnReturn; @Value("${spring.datasource.poolPreparedStatements}") private boolean poolPreparedStatements; @Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}") private int maxPoolPreparedStatementPerConnectionSize; @Value("${spring.datasource.filters}") private String filters; @Value("{spring.datasource.connectionProperties}") private String connectionProperties; @Bean(name = "masterDataSource") @Primary //标志这个 Bean 如果在多个同类 Bean 候选时,该 Bean 优先被考虑。 public DataSource masterDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); dataSource.setDriverClassName(driverClassName); //具体配置 dataSource.setInitialSize(initialSize); dataSource.setMinIdle(minIdle); dataSource.setMaxActive(maxActive); dataSource.setMaxWait(maxWait); dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); dataSource.setValidationQuery(validationQuery); dataSource.setTestWhileIdle(testWhileIdle); dataSource.setTestOnBorrow(testOnBorrow); dataSource.setTestOnReturn(testOnReturn); dataSource.setPoolPreparedStatements(poolPreparedStatements); dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); * 这个是用来配置 druid 监控sql语句的 非常有用 如果你有两个数据源 这个配置哪个数据源就监控哪个数据源的sql 同时配置那就都监控 try { dataSource.setFilters(filters); } catch (SQLException e) { e.printStackTrace(); dataSource.setConnectionProperties(connectionProperties); return dataSource; @Bean(name = "masterTransactionManager") @Primary public DataSourceTransactionManager masterTransactionManager() { return new DataSourceTransactionManager(masterDataSource()); @Bean(name = "masterSqlSessionFactory") @Primary public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(masterDataSource); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MasterDataSourceConfig.MAPPER_LOCATION)); return sessionFactory.getObject();

这里说明几点

  1) @Primary: 多数据源配置的时候注意,必须要有一个主数据源, 用 @Primary 标志该 Bean。标志这个 Bean 如果在多个同类 Bean 候选时,该 Bean优先被考虑。
  2) dataSource.setFilters(filters): 这个是用来配置 druid 监控sql语句的, 如果你有两个数据源 这个配置哪个数据源就监控哪个 数据源的sql,同时配置那就都监控。
  3) 能够做到多个数据源的关键点 就是每个数据源所扫描的mapper包不一样,谁扫描到哪个mapper那么该mapper就用哪个数据源,同时都扫到了呢,
      那当然就得用主数据源咯,也就是添加@Primary 的数据源。

4、次数据源(ClusterDataSourceConfig)

这里省略了部分代码,因为和主是一样的,完整代码在github代码里有。

* 次数据源 另一个数据源配置 @Configuration @MapperScan(basePackages = ClusterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "clusterSqlSessionFactory") public class ClusterDataSourceConfig { * 配置多数据源 关键就在这里 这里配置了不同数据源扫描不同的mapper static final String PACKAGE = "com.binron.multidatasource.mapper.cluster"; static final String MAPPER_LOCATION = "classpath:mapper/cluster/*.xml"; @Value("${cluster.datasource.url}") private String url; @Value("${cluster.datasource.username}") private String username; @Value("${cluster.datasource.password}") private String password; @Value("${cluster.datasource.driverClassName}") private String driverClass; @Bean(name = "clusterDataSource") public DataSource clusterDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); dataSource.setDriverClassName(driverClass); //具体配置 try { dataSource.setFilters("stat,wall,slf4j"); } catch (SQLException e) { e.printStackTrace(); return dataSource; @Bean(name = "clusterTransactionManager") public DataSourceTransactionManager clusterTransactionManager() { return new DataSourceTransactionManager(clusterDataSource()); @Bean(name = "clusterSqlSessionFactory") public SqlSessionFactory clusterSqlSessionFactory(@Qualifier("clusterDataSource") DataSource clusterDataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(clusterDataSource); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(ClusterDataSourceConfig.MAPPER_LOCATION)); return sessionFactory.getObject();

这里说明几点:

   1)发现次数据源所扫描的mapper和主是完全不一样的,说明每个数据源负责自己的mapper
   2)  次数据源是没有加@Primary。
   3)这里也添加了dataSource.setFilters(filters):说明 次数据源也需要监听sql语句。

三、配置可视化界面

直接上代码:

* druid监控界面设置 @Configuration public class DruidConfiguration { @Bean public ServletRegistrationBean druidStatViewServle() { //注册服务 ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean( new StatViewServlet(), "/druid/*"); // 白名单(为空表示,所有的都可以访问,多个IP的时候用逗号隔开) servletRegistrationBean.addInitParameter("allow", "127.0.0.1"); // IP黑名单 (存在共同时,deny优先于allow) (黑白名单就是如果是黑名单,那么该ip无法登陆该可视化界面) servletRegistrationBean.addInitParameter("deny", "127.0.0.2"); // 设置登录的用户名和密码 servletRegistrationBean.addInitParameter("loginUsername", "root"); servletRegistrationBean.addInitParameter("loginPassword", "123456"); // 是否能够重置数据. servletRegistrationBean.addInitParameter("resetEnable", "false"); return servletRegistrationBean; @Bean public FilterRegistrationBean druidStatFilter() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean( new WebStatFilter()); // 添加过滤规则 filterRegistrationBean.addUrlPatterns("/*"); // 添加不需要忽略的格式信息 filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); System.out.println("druid初始化成功!"); return filterRegistrationBean;

这里说明几点

(1)登陆地址:http://127.0.0.1:8080/druid/index.html(端口号看自己设置的端口号)
(2)一旦配置黑名单,那么该ip访问是没有权限的登陆的
(3)如果想看SQL执行结果,那么上面数据源配置一定要添加dataSource.setFilters(filters),我之前就没有添加,所以其它都能正常使用,就是无法监控Sql语句。

确实很好用。顺便讲下,我遇到其它功能都有用,唯独Sql语句无法监控的问题,之后看界面才看出端倪来。

我发现界面中,filter类名为空,可是在yml确实配置了filters,怎么还是空,原因是数据源里没有配置setFilters(filters)

1、 阿里github有关Druid结合Boot文档
2、 demo参考github地址: (感谢作者分享)
3、 数据连接池的属性字段说明
4、 yml配置、properties配置、ssm配置