先献上 GitHub 代码地址:
代码拉下来换下自己的 MySQL 数据库地址, 就可以直接运行. Druid 的优点很明显, 它的可视化界面可以监控 Sql 语句和 URI 执行情况在开发中真的很需要.
先说优点吧:
) 替换 DBCP 和 C3P0.Druid 提供了一个高效, 功能强大, 可扩展性好的数据库连接池.
) 数据库密码加密. 直接把数据库密码写在配置文件中, 这是不好的行为, 容易导致安全问题.
) 可以监控数据库访问性能, 能够详细统计 SQL 的执行性能, 这对于线上分析数据库访问性能有帮助.
) SQL 执行日志, Druid 提供了不同的 LogFilter, 监控你应用的数据库 访问情况.
) 扩展 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.YAML
我这里是采用 application.YAML 进行添加配置, 这里面配置了两个数据源, 其实在 application.YAML 也可以不配置这些东西, 它的主要作用是给数据源配置类读取数据用的.
- 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();
- }
- }
这里说明几点:
) 发现次数据源所扫描的 mapper 和主是完全不一样的, 说明每个数据源负责自己的 mapper
) 次数据源是没有加 @Primary.
) 这里也添加了 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 类名为空, 可是在 YAML 确实配置了 filters, 怎么还是空, 原因是数据源里没有配置
- setFilters(filters)
- .
文献资料
1, 阿里 GitHub 有关 Druid 结合 Boot 文档
2, demo 参考 GitHub 地址 https://github.com/xuwujing/springBoot-study : (感谢作者分享)
3, 数据连接池的属性字段说明
4, YAML 配置, properties 配置, ssm 配置 https://www.jianshu.com/p/1094d3fcee8d
来源: https://www.cnblogs.com/qdhxhz/p/10192041.html