MySQL专栏 | ||
上一篇 | 主目录 | 下一篇 |
目录
- 1 基本概念
- 1.1 数据源DataSource、连接池
- 1.2 连接池思想
- 2 数连接池分类
- 2.1 Hikari连接池
- 2.2 阿里druid
【前言】
我们在进行数据访问都需要配置数据源用来连接数据库。数据源又可以分为两大类:直连的数据源 和 连接池的数据源 ,其中连接池的数据源又有多种。
1 基本概念
1.1 数据源DataSource、连接池
DataSource
通常被称为数据源,它包含连接池 和连接池管理 两部分,习惯上也经常把DataSource称为连接池。
Java中的数据源就是连接到数据库的一条路径,数据源中并无真正的数据,它仅仅记录的是你连接到哪个数据库,以及如何连接。
1.2 连接池思想
在系统初始化的时候,将数据库连接对象(Connection) 存储在内存中,当用户需要访问数据库时候,并不是建立一个新的连接,而是从连接池中取出一个已经建立好的空闲连接对象。而连接池负责分配、管理、释放数据库连接对象。注意的是:连接池是由容器(比如tomcat) 提供的,同时容器也管理着连接池。
2 数连接池分类
数据库连接池有C3P0、Tomcat、BoneCP、Hikari以及阿里的druid等。HikariCP 的性能比 Druid 高,但是因为 Druid 包括很多维度的统计和分析功能。以下介绍:
2.1 Hikari连接池
HikariCP
(HikariCP:Hikari Connection Pool):Hikari日文中是“光”的意思,寓意着飞快。同时也是一个可靠连接池
数据连接配置:
<!-- Hikari Datasource -->
<bean id="dataSourceHikari" class="com.zaxxer.hikari.HikariDataSource" destroy-method="shutdown">
<!-- <property name="driverClassName" value="${db.driverClass}" /> --> <!-- 无需指定,除非系统无法自动识别 -->
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
<!-- 连接只读数据库时配置为true, 保证安全 -->
<property name="readOnly" value="false" />
<!-- 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒 -->
<property name="connectionTimeout" value="30000" />
<!-- 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟 -->
<property name="idleTimeout" value="600000" />
<!-- 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒,参考MySQL wait_timeout参数(show variables like '%timeout%';) -->
<property name="maxLifetime" value="1800000" />
<!-- 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count) -->
<property name="maximumPoolSize" value="15" />
</bean>
2.2 阿里druid
Druid是阿里巴巴开源的一个数据源,主要用于java数据库连接池。官方参考文档
使用方法:
(1) 添加Druid依赖
<properties>
<druid-version>1.1.10</druid-version>
</properties>
<dependencies>
......
<!--alibaba druid datasource-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${alibaba-druid.version}</version>
</dependency>
......
</dependencies>
(2) 添加application.properties配置
springboot支持yml和properties等配置文件,本文采用application.properties配置。
# DataSource settings
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url = jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF8
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driverClassName = com.mysql.jdbc.Driver
#连接池的配置信息
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
druid-monitor.properties
#是否启用StatFilter默认值true
spring.datasource.druid.web-stat-filter.enabled=true
#多个白名单IP以逗号分隔
druid.monitor.allow=127.0.0.1
#多个黑名单IP以逗号分隔
druid.monitor.deny=0.0.0.0
#druid监控管理界面登录帐号
druid.monitor.loginUsername=admin
#druid监控管理界面登录密码
druid.monitor.loginPassword=password
#是否开启重置功能
druid.monitor.resetEnable=false
(3) 添加配置类
为方便以后拓展,这里提供一个数据源配置接口,druid配置也只是这个接口的一个实现类,方便以后切换不同的数据源;
DbConfig.java
package com.ijustone.service.core.db.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
public interface DbConfig {
/**
* 定义数据源
*
* @return
* @throws Exception
*/
DataSource dataSource() throws Exception;
/**
* 定义session工厂
*
* @param dataSource
* @return
* @throws Exception
*/
SqlSessionFactory sessionFactory(DataSource dataSource) throws Exception;
/**
* 定义失误管理器
*
* @param dataSource
* @return
*/
DataSourceTransactionManager transactionManager(DataSource dataSource);
}
下面是druid配置实现类
MyDruirdConfig.java
package com.ijustone.service.core.db.config.impl;
import com.alibaba.druid.pool.DruidDataSource;
import com.ijustone.service.core.db.config.DbConfig;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
/**
* @author JustOne
* @create 2018-08-01 22:47
*/
@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = MyDruirdConfig.PACKAGE, sqlSessionFactoryRef = "sessionFactory")
public class MyDruirdConfig implements DbConfig {
public static final String PACKAGE = "com.ijustone.service.**.mapper";
public static final String MAPPER = "classpath:com/ijustone/service/**/mapper/**/*Mapper.xml";
@Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.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.testWhileIdle:true}")
private boolean testWhileIdle;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis:60000}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.validationQuery}")
private String validationQuery;
/**
* 指明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个.<br/>
* 注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
*/
@Value("${spring.datasource.testOnBorrow:true}")
private boolean testOnBorrow;
/**
* 指明是否在归还到池中前进行检验<br/>
* 注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
*/
@Value("${spring.datasource.testOnReturn:false}")
private boolean testOnReturn;
@Value("${spring.datasource.minEvictableIdleTimeMillis:300000}")
private int minEvictableIdleTimeMillis;
/**
* 当开启时, 将为每个连接创建一个statement池,并且被方法创建的PreparedStatements将被缓存起来:
*/
@Value("${spring.datasource.poolPreparedStatements:false}")
private boolean poolPreparedStatements;
/**
* 不限制 statement池能够同时分配的打开的statements的最大数量,如果设置为0表示不限制
*/
@Value("${spring.datasource.maxOpenPreparedStatements:10}")
private int maxPoolPreparedStatementPerConnectionSize;
@Value("${spring.datasource.defaultAutoCommit:false}")
private boolean defaultAutoCommit;
@Value("${spring.datasource.filters:stat}")
private String filters;
/**
* 当建立新连接时被发送给JDBC驱动的连接参数
*/
@Value("${spring.datasource.connectionProperties:druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000}")
private String connectionProperties;
/**
* 定义数据源
* 注意@Primary注解表示:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
*
* @return
* @throws Exception
*/
@Bean(name = "dataSource")
@Primary
@Override
public DataSource dataSource() throws Exception {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(this.dbUrl);
datasource.setUsername(this.username);
datasource.setPassword(this.password);
datasource.setDriverClassName(this.driverClassName);
datasource.setInitialSize(this.initialSize);
datasource.setMinIdle(this.minIdle);
datasource.setMaxActive(this.maxActive);
datasource.setMaxWait(this.maxWait);
datasource.setTimeBetweenEvictionRunsMillis(this.timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(this.minEvictableIdleTimeMillis);
datasource.setValidationQuery(this.validationQuery);
datasource.setTestWhileIdle(this.testWhileIdle);
datasource.setTestOnBorrow(this.testOnBorrow);
datasource.setTestOnReturn(this.testOnReturn);
datasource.setPoolPreparedStatements(this.poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(this.maxPoolPreparedStatementPerConnectionSize);
datasource.setDefaultAutoCommit(this.defaultAutoCommit);
datasource.setFilters(this.filters);
datasource.setConnectionProperties(this.connectionProperties);
return datasource;
}
/**
* 定义session工厂
* 注:ualifier的意思是合格者,通过这个标示,表明了哪个实现类才是我们所需要的,
* 我们修改调用代码,添加@Qualifier注解,需要注意的是@Qualifier的参数名称必须为我们之前定义@Service注解的名称之一!
*
* @param dataSource
* @return
* @throws Exception
*/
@Bean(name = "sessionFactory")
@Primary
@Override
public SqlSessionFactory sessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sessionFactory.setMapperLocations(resolver.getResources(MyDruirdConfig.MAPPER));
return sessionFactory.getObject();
}
/**
* 定义事务管理器
*
* @param dataSource
* @return
*/
@Bean(name = "transactionManager")
@Override
public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
我们配置了Druid的监听器
DruidMonitorConfiguration.java
package com.ijustone.service.core.druid.monitor;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.beans.factory.annotation.Value;
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.PropertySource;
@Configuration
@PropertySource(value = "classpath:config/druid-monitor.properties")
@ConfigurationProperties
public class DruidMonitorConfiguration {
@Value("${druid.monitor.allow:127.0.0.1}")
private String allow;
@Value("${druid.monitor.deny}")
private String deny;
@Value("${druid.monitor.loginUsername:admin}")
private String loginUsername;
@Value("${druid.monitor.loginPassword:password}")
private String loginPassword;
@Value("${druid.monitor.resetEnable:false}")
private String resetEnable;
@Bean
public ServletRegistrationBean druidStatViewServlet() {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
servletRegistrationBean.addInitParameter("allow", this.allow);
servletRegistrationBean.addInitParameter("deny", this.deny);
servletRegistrationBean.addInitParameter("loginUsername", this.loginUsername);
servletRegistrationBean.addInitParameter("loginPassword", this.loginPassword);
servletRegistrationBean.addInitParameter("resetEnable", this.resetEnable);
return servletRegistrationBean;
}
@Bean
public FilterRegistrationBean druidStatFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
}
如何查看监控页面?
访问http://localhost:8010/druid就可以了