初學SpringBoot,在學習過程當中遇到許多問題,因此分享出來;css
在集成Druid數據鏈接池時,因爲SpringBoot默認沒有該配置,須要咱們配置,所以花費了好些時間,才整理出來比較簡潔的配置方案html
首先新建好SpringBoot項目,java
1: pom.xml 文件中 引入Jar包:mysql
<!-- MySql數據庫 begin--> <dependency><!--驅動--> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <dependency><!--鏈接池--> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.20</version> </dependency> <!-- 注意: 在配置過程當中 mysql-connector-java 的版本號會 和 druid 衝突,從而 在項目啓動時發出: com.alibaba.druid.pool.vendor.MySqlValidConnectionChecker - Cannot resolve com.mysq.jdbc.Connection.ping method. Will use 'SELECT 1' instead. 的警告; 因此注意 mysql-connector-java 的版本 --> <!-- MySql數據庫 end -->
2: application.yml 文件中 進行數據配置:git
spring: #數據源 datasource: #數據庫訪問配置 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/diary?autoReconnect=true&characterEncoding=utf-8 username: root password: 123456 #鏈接池配置 # 初始化時創建物理鏈接的個數 initialSize: 1 # 最小鏈接池數量 minIdle: 1 # 最大鏈接池數量 maxActive: 20 # 鏈接時最大等待時間,單位毫秒 maxWait: 60000 # 配置間隔多久才進行一次檢測,檢測須要關閉的空閒鏈接,單位是毫秒 timeBetweenEvictionRunsMillis: 60000 # 配置一個鏈接在池中最小生存的時間,單位是毫秒 minEvictableIdleTimeMillis: 300000 # 用來檢測鏈接是否有效的sql,要求是一個查詢語句 validationQuery: SELECT 1 FROM DUAL # 申請鏈接時執行 validationQuery 檢測鏈接是否有效,作了這個配置會下降性能 testOnBorrow: false # 歸還鏈接時執行 validationQuery 檢測鏈接是否有效,作了這個配置會下降性能 testOnReturn: false # 建議配置爲true,不影響性能,而且保證安全性;申請鏈接的時候檢測, # 若是空閒時間大於 timeBetweenEvictionRunsMillis,執行 validationQuery 檢測鏈接是否有效 testWhileIdle: true # 是否緩存preparedStatement,也就是 PSCache poolPreparedStatements: true # 指定每一個鏈接上 PSCache 的大小 maxOpenPreparedStatements: 20 # 配置監控統計攔截的filters,屬性類型是字符串,經過別名的方式配置擴展插件, # 經常使用的插件有:監控統計用的stat;日誌用的log4j;防護sql注入的wall filters: stat,wall,log4j # 經過 connectProperties 屬性來打開mergeSql功能;慢SQL記錄 connectionProperties: druid.stat.merggSql=ture;druid.stat.slowSqlMillis=5000 # 合併多個DruidDataSource的監控數據 useGlobalDataSourceStat: true
3: 編寫配置文件:web
package com.gy.demo.config.druid; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import javax.sql.DataSource; /** * Description : 數據源配置 * Created by com on 2017/12/6 * * @author geYang **/ @Configuration public class DruidConfig { private Logger logger = LoggerFactory.getLogger(DruidConfig.class); //配置數據源的信息 方法一: @Bean(name = "dataSource") @Primary @ConfigurationProperties(prefix = "spring.datasource") public DataSource dataSource() { logger.info("Druid: 開始注入數據源 方法一"); return DataSourceBuilder.create().type(DruidDataSource.class).build(); } //======= 監控統計配置 ======= @Bean public ServletRegistrationBean statViewServlet(){ logger.info("Druid: 配置監控統計的登陸信息"); ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*"); //白名單: servletRegistrationBean.addInitParameter("allow","192.168.102.6,127.0.0.1"); //IP黑名單 (存在共同時,deny優先於allow) : 若是知足deny的即提示:Sorry, you are not permitted to view this page. servletRegistrationBean.addInitParameter("deny","192.168.102.6"); //登陸查看信息的帳號密碼. servletRegistrationBean.addInitParameter("loginUsername","admin"); servletRegistrationBean.addInitParameter("loginPassword","admin"); //是否可以重置數據. servletRegistrationBean.addInitParameter("resetEnable","false"); return servletRegistrationBean; } @Bean public FilterRegistrationBean statFilter(){ logger.info("Druid: 配置監控統計的過濾信息"); FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter()); //添加過濾規則. filterRegistrationBean.addUrlPatterns("/*"); //添加不須要忽略的格式信息.(監控排除的資源) filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); return filterRegistrationBean; } }
配置到這基本上就可使用了.不過,仍是要注意MySql驅動的版本,避免與Druid衝突,其實儘管衝突,但運行仍是正常的,不會有什麼影響,可是像我這樣有強迫症的每次啓動都要報警告,很不舒服,而後就找問題,找了很久;開始覺得是配置有問題,因此還換了一種配置方式也很好用:spring
(1): 封裝Druid數據特性:sql
package com.gy.demo.config.druid; import org.springframework.boot.context.properties.ConfigurationProperties; /** * Description : Druid 數據源特性實體類 * Created by com on 2017/12/11 * * @author geYang **/ @ConfigurationProperties(prefix = "spring.datasource") public class DruidEntity { private String driverClassName; private String url; private String username; private String password; private String validationQuery; private String filters; private String connectionProperties; private Boolean testOnBorrow; private Boolean testOnReturn; private Boolean testWhileIdle; private Boolean poolPreparedStatements; private Boolean useGlobalDataSourceStat; private Integer initialSize; private Integer minIdle; private Integer maxActive; private Integer maxWait; private Integer timeBetweenEvictionRunsMillis; private Integer minEvictableIdleTimeMillis; private Integer maxOpenPreparedStatements; public String getDriverClassName () { return driverClassName; } public void setDriverClassName (String driverClassName) { this.driverClassName = driverClassName; } public String getUrl () { return url; } public void setUrl (String url) { this.url = url; } public String getUsername () { return username; } public void setUsername (String username) { this.username = username; } public String getPassword () { return password; } public void setPassword (String password) { this.password = password; } public String getValidationQuery () { return validationQuery; } public void setValidationQuery (String validationQuery) { this.validationQuery = validationQuery; } public String getFilters () { return filters; } public void setFilters (String filters) { this.filters = filters; } public String getConnectionProperties () { return connectionProperties; } public void setConnectionProperties (String connectionProperties) { this.connectionProperties = connectionProperties; } public Boolean getTestOnBorrow () { return testOnBorrow; } public void setTestOnBorrow (Boolean testOnBorrow) { this.testOnBorrow = testOnBorrow; } public Boolean getTestOnReturn () { return testOnReturn; } public void setTestOnReturn (Boolean testOnReturn) { this.testOnReturn = testOnReturn; } public Boolean getTestWhileIdle () { return testWhileIdle; } public void setTestWhileIdle (Boolean testWhileIdle) { this.testWhileIdle = testWhileIdle; } public Boolean getPoolPreparedStatements () { return poolPreparedStatements; } public void setPoolPreparedStatements (Boolean poolPreparedStatements) { this.poolPreparedStatements = poolPreparedStatements; } public Boolean getUseGlobalDataSourceStat () { return useGlobalDataSourceStat; } public void setUseGlobalDataSourceStat (Boolean useGlobalDataSourceStat) { this.useGlobalDataSourceStat = useGlobalDataSourceStat; } public Integer getInitialSize () { return initialSize; } public void setInitialSize (Integer initialSize) { this.initialSize = initialSize; } public Integer getMinIdle () { return minIdle; } public void setMinIdle (Integer minIdle) { this.minIdle = minIdle; } public Integer getMaxActive () { return maxActive; } public void setMaxActive (Integer maxActive) { this.maxActive = maxActive; } public Integer getMaxWait () { return maxWait; } public void setMaxWait (Integer maxWait) { this.maxWait = maxWait; } public Integer getTimeBetweenEvictionRunsMillis () { return timeBetweenEvictionRunsMillis; } public void setTimeBetweenEvictionRunsMillis (Integer timeBetweenEvictionRunsMillis) { this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; } public Integer getMinEvictableIdleTimeMillis () { return minEvictableIdleTimeMillis; } public void setMinEvictableIdleTimeMillis (Integer minEvictableIdleTimeMillis) { this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; } public Integer getMaxOpenPreparedStatements () { return maxOpenPreparedStatements; } public void setMaxOpenPreparedStatements (Integer maxOpenPreparedStatements) { this.maxOpenPreparedStatements = maxOpenPreparedStatements; } }
(2)進行數據配置:數據庫
package com.gy.demo.config.druid; import com.alibaba.druid.pool.DruidDataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import javax.annotation.Resource; import javax.sql.DataSource; import java.sql.SQLException; /** * Description : Druid自動配置方法二 * Created by com on 2017/12/11 * * @author geYang **/ @Configuration @ConditionalOnClass(DruidDataSource.class) @EnableConfigurationProperties(DruidEntity.class) @AutoConfigureBefore(DataSourceAutoConfiguration.class) public class DruidConfigTow { private static final Logger logger = LoggerFactory.getLogger(DruidConfigTow.class); @Resource private DruidEntity druidEntity; @Bean public DataSource dataSource() { logger.info("Druid: 開始注入數據源 方法二"); DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(druidEntity.getUrl()); dataSource.setUsername(druidEntity.getUsername()); dataSource.setPassword(druidEntity.getPassword()); dataSource.setDriverClassName(druidEntity.getDriverClassName()); if (druidEntity.getValidationQuery()!=null){ dataSource.setValidationQuery(druidEntity.getValidationQuery()); logger.info("Druid: 注入 validationQuery"); } if (druidEntity.getFilters()!=null){ try { dataSource.setFilters(druidEntity.getFilters()); logger.info("Druid: 注入 filters 成功"); } catch (SQLException e) { e.printStackTrace(); logger.info("Druid: 注入 filters 失敗"); } } if (druidEntity.getConnectionProperties()!=null){ dataSource.setConnectionProperties(druidEntity.getConnectionProperties()); logger.info("Druid: 注入 connectionProperties"); } if (druidEntity.getTestOnBorrow()!=null){ dataSource.setTestOnBorrow(druidEntity.getTestOnBorrow()); logger.info("Druid: 注入 testOnBorrow"); } if (druidEntity.getTestOnReturn()!=null){ dataSource.setTestOnReturn(druidEntity.getTestOnReturn()); logger.info("Druid: 注入 testOnReturn"); } if (druidEntity.getTestWhileIdle()!=null){ dataSource.setTestWhileIdle(druidEntity.getTestWhileIdle()); logger.info("Druid: 注入 testWhileIdle"); } if (druidEntity.getPoolPreparedStatements()!=null){ dataSource.setPoolPreparedStatements(druidEntity.getPoolPreparedStatements()); logger.info("Druid: 注入 poolPreparedStatements"); } if (druidEntity.getUseGlobalDataSourceStat()!=null){ dataSource.setUseGlobalDataSourceStat(druidEntity.getUseGlobalDataSourceStat()); logger.info("Druid: 注入 useGlobalDataSourceStat"); } if (druidEntity.getInitialSize()>0){ dataSource.setInitialSize(druidEntity.getInitialSize()); logger.info("Druid: 注入 initialSize"); } if (druidEntity.getMinIdle()>0){ dataSource.setMinIdle(druidEntity.getMinIdle()); logger.info("Druid: 注入 initialSize"); } if (druidEntity.getMaxActive()>0){ dataSource.setMaxActive(druidEntity.getMaxActive()); logger.info("Druid: 注入 initialSize"); } if (druidEntity.getMaxWait()>0){ dataSource.setMaxWait(druidEntity.getMaxWait()); logger.info("Druid: 注入 maxWait"); } if (druidEntity.getTimeBetweenEvictionRunsMillis()>0){ dataSource.setTimeBetweenEvictionRunsMillis(druidEntity.getTimeBetweenEvictionRunsMillis()); logger.info("Druid: 注入 timeBetweenEvictionRunsMillis"); } if (druidEntity.getMinEvictableIdleTimeMillis()>0){ dataSource.setMinEvictableIdleTimeMillis(druidEntity.getMinEvictableIdleTimeMillis()); logger.info("Druid: 注入 minEvictableIdleTimeMillis"); } if (druidEntity.getMaxOpenPreparedStatements()>0){ dataSource.setMaxOpenPreparedStatements(druidEntity.getMaxOpenPreparedStatements()); logger.info("Druid: 注入 maxOpenPreparedStatements"); } // 初始化 try { dataSource.init(); logger.info("Druid: dataSource.init() 成功"); } catch (SQLException e) { logger.info("Druid: dataSource.init() 失敗"); e.printStackTrace(); } return dataSource; } }
(注: 這的方法二,和上面的方法一功能都是相同的,兩種方法不會同時使用,若是兩個都配置上,則會執行方法一,使用用方法二時,須註釋掉方法一(DruidConfig類中的dataSource() 方法;)apache
使用第二種方法配置後,也發生了啓動警告;所以去百度了一下,才發現原來是MySQL驅動版本的問題;
將 mysql-connector-java 的jar包版本 由 5.1.6 改成 5.1.38 後就沒有出現警告問題;
SpringBoot 與 Druid 的集成配置就基本完成了;
SpringBoot官方文檔: https://docs.spring.io/spring-boot/docs/current/reference/html/