All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.druid.spring.boot.util.DruidDataSourceUtils Maven / Gradle / Ivy

There is a newer version: 1.0.6.RELEASE
Show newest version
package com.alibaba.druid.spring.boot.util;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.jdbc.DatabaseDriver;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.logging.LogFilter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.DruidProperties;
import com.alibaba.druid.wall.WallFilter;

public class DruidDataSourceUtils {

	public static  DruidDataSource createDataSource(DataSourceProperties properties, DruidProperties druidProperties,
			String name, String url, String username, String password) {
		// 创建 DruidDataSource 数据源对象
		DruidDataSource dataSource = createDataSource(properties, properties.getType());

		// 配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。如果没有配置,将会生成一个名字,格式是:”DataSource-” +
		// System.identityHashCode(this)
		if (StringUtils.isNotEmpty(name)) {
			dataSource.setName(name);
		}
		// 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName
		dataSource.setDriverClassName(properties.determineDriverClassName());
		// jdbcUrl: 连接数据库的url
		dataSource.setUrl(url);
		// username: 连接数据库的用户名
		dataSource.setUsername(username);
		// password: 连接数据库的密码
		dataSource.setPassword(password);

		// druid 连接池参数
		dataSource.configFromPropety(druidProperties.toProperties());
		//DruidDataSourceFactory.config(dataSource, druidProperties);
		
		// 配置初始化大小、最小、最大

		// minIdle: 最小空闲连接数量
		dataSource.setMinIdle(druidProperties.getMinIdle());
		// maxActive: 最大连接池数量
		dataSource.setMaxActive(druidProperties.getMaxActive());
		// initialSize: 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
		dataSource.setInitialSize(druidProperties.getInitialSize());
		// 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
		dataSource.setMaxWait(druidProperties.getMaxWait());
		// 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒;有两个含义:1) Destroy线程会检测连接的间隔时间 2)
		// testWhileIdle的判断依据,详细看testWhileIdle属性的说明
		dataSource.setTimeBetweenEvictionRunsMillis(druidProperties.getTimeBetweenEvictionRunsMillis());
		// 配置一个连接在池中最小生存的时间,单位是毫秒
		dataSource.setMinEvictableIdleTimeMillis(druidProperties.getMinEvictableIdleTimeMillis());
		// 超过时间限制是否回收
		dataSource.setRemoveAbandoned(druidProperties.getRemoveAbandoned());
		// 超过时间限制多长,单位是毫秒
		dataSource.setRemoveAbandonedTimeoutMillis(druidProperties.getRemoveAbandonedTimeoutMillis());

		if (StringUtils.isNotEmpty(druidProperties.getValidationQuery())) {
			// 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
			dataSource.setTestOnBorrow(druidProperties.getTestOnBorrow());
			// 用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。
			dataSource.setValidationQuery(druidProperties.getValidationQuery());
		} else {
			DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(properties.determineUrl());
			String validationQuery = databaseDriver.getValidationQuery();
			if (validationQuery != null) {
				dataSource.setTestOnBorrow(druidProperties.getTestOnBorrow());
				dataSource.setValidationQuery(validationQuery);
			}
		}

		// 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。建议配置为true,不影响性能,并且保证安全性。
		dataSource.setTestWhileIdle(druidProperties.getTestWhileIdle());

		// 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
		dataSource.setTestOnReturn(druidProperties.getTestOnReturn());

		// 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql5.5以下的版本中没有PSCache功能,建议关闭掉。5.5及以上版本有PSCache,建议开启。
		dataSource.setPoolPreparedStatements(druidProperties.getPoolPreparedStatements());
		// 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
		dataSource.setMaxOpenPreparedStatements(druidProperties.getMaxPoolPreparedStatementPerConnectionSize());

		/*
		 * Druid的监控统计功能:属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: #监控统计用的filter:stat
		 * #日志用的filter:log4j #防御SQL注入的filter:wall
		 */
		try {
			// 指定过滤器
			if (BooleanUtils.isTrue(druidProperties.getProxyFilter())) {
				dataSource.setProxyFilters(getProxyFilters(druidProperties));
			} else {
				dataSource.setFilters(druidProperties.getFilters());
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}

		// 额外的链接参数
		dataSource.setConnectProperties(druidProperties.getConnectionProperties());

		// 注册对象到上下文
		// configurableBeanFactory.registerSingleton(dataSource.getName(), dataSource);

		return dataSource;
	}

	@SuppressWarnings("unchecked")
	public static  T createDataSource(DataSourceProperties properties, Class type) {
		return (T) properties.initializeDataSourceBuilder().type(type).build();
	}

	/**
	 * 
	 * @description : TODO
	 * @author : 万大龙(743)
	 * @date :2017年10月16日 下午12:22:30
	 * @param druidProperties
	 * @return
	 * @see https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE-wallfilter
	 */
	public static List getProxyFilters(DruidProperties druidProperties) {

		List filters = new ArrayList();

		WallFilter wallFilter = druidProperties.getWallFilter();
		if (null != wallFilter) {
			filters.add(wallFilter);
		}

		StatFilter statFilter = druidProperties.getStatFilter();
		if (null != statFilter) {
			filters.add(statFilter);
		}

		LogFilter logFilter = druidProperties.getLogFilter();
		if (null != logFilter) {
			filters.add(logFilter);
		}

		return filters;
	}

	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy