SpringBoot-Druid 框架搭建

初學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/

項目配置源碼: https://gitee.com/ge.yang/SpringBoot

相關文章
相關標籤/搜索