文章目录
++springboot版本–>2.3.1.RELEASE
druid版本–>1.1.23++
一、Druid数据源是什么?
Druid是阿里巴巴开源的一个数据源,主要用于java数据库连接池,相比spring推荐的DBCP和hibernate推荐的C3P0、Proxool数据库连接池,Druid在市场上占有绝对的优势;
二、为什么选择Druid作为数据库连接池?
这里直接给出一个链接:https://www.jianshu.com/p/53de4b76f98c
文章从市场占有率、性能上比较C3P0、DBCP、HikariCP和Druid,说明了Druid数据源由于有强大的监控特性、可拓展性等特点值得作者推荐。虽说 HikariCP 的性能比 Druid 高,但是因为 Druid 包括很多维度的统计和分析功能,所以大家都选择使用Druid的更多
三、如何使用springboot整合druid的数据库
springboot作为web开发的主流框架,再加上如此优秀的开源数据源岂不美哉?但是,由于springboot和druid的持续更新,配置参数又有很多改变之处,我被绕晕了。后来,我借鉴了很多csdn的博主的方法和官方文档(https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter),最后我总结了整合druid的两种方法
1、使用yaml配置文件整合(推荐)
这种方法只需配置配置文件,让我们导入stater场景启动器依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.23</version>
</dependency>
注:导入场景启动器后,配置文件中就有druid关键字提示,starter自动引入druid依赖,无需我们再次引入
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.23</version>
</dependency>
我采用了yaml的配置文件,因为properties一点都不香。
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource #引入druid数据源
#数据源基本信息,也可放在druid下
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
druid:
#SpringBoot因为默认是hikari数据源所以对于其他数据源默认是不注入这些属性的,需要手动配置
#druid数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 600000
# 主要配置以上几个即可
timeBetweenEvictionRunsMillis: 600000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters:stat:监控统计、self4j(使用log4j的记得导入log4j的依赖):日志记录、wall:防御sql注入 此处配置不能遗漏服务sql监控台不能监控sql
filter:
slf4j:
enabled: true
stat:
enabled: true
merge-sql: true
slow-sql-millis: 5000
wall:
enabled: true
#配置stat-view-servlet
stat-view-servlet:
enabled: true
login-username: admin
login-password: 123456
reset-enable: false
#配置web-stat-filter
web-stat-filter:
enabled: true
怎么得出的这些配置呢?
我默默的打开了com.alibaba.druid.spring.boot.autoconfigure的自动配置包想看一下源码是怎么配置的
找到DruidDataSourceAutoConfigure的自动配置类
@Configuration
@ConditionalOnClass(DruidDataSource.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
@Import({DruidSpringAopConfiguration.class,
DruidStatViewServletConfiguration.class,
DruidWebStatFilterConfiguration.class,
DruidFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {
private static final Logger LOGGER = LoggerFactory.getLogger(DruidDataSourceAutoConfigure.class);
@Bean(initMethod = "init")
@ConditionalOnMissingBean
public DataSource dataSource() {
LOGGER.info("Init DruidDataSource");
return new DruidDataSourceWrapper();
}
}
发现只配置了数据源,我继续进入@Import注解导入的其他配置类
- DruidSpringAopConfiguration.class:AOP配置
- DruidStatViewServletConfiguration.class:statservlet的监控配置
- DruidWebStatFilterConfiguration.class:statfilter的监控配置
- DruidFilterConfiguration.class:各种其他的filter配置
进入DruidStatViewServletConfiguration.class
@ConditionalOnWebApplication
@ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true")
public class DruidStatViewServletConfiguration {
private static final String DEFAULT_ALLOW_IP = "127.0.0.1";
@Bean
public ServletRegistrationBean statViewServletRegistrationBean(DruidStatProperties properties) {
DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean();
registrationBean.setServlet(new StatViewServlet());
registrationBean.addUrlMappings(config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*");
if (config.getAllow() != null) {
registrationBean.addInitParameter("allow", config.getAllow());
} else {
registrationBean.addInitParameter("allow", DEFAULT_ALLOW_IP);
}
if (config.getDeny() != null) {
registrationBean.addInitParameter("deny", config.getDeny());
}
if (config.getLoginUsername() != null) {
registrationBean.addInitParameter("loginUsername", config.getLoginUsername());
}
if (config.getLoginPassword() != null) {
registrationBean.addInitParameter("loginPassword", config.getLoginPassword());
}
if (config.getResetEnable() != null) {
registrationBean.addInitParameter("resetEnable", config.getResetEnable());
}
return registrationBean;
}
}
StatViewServlet默认情况下是关闭的,只要我们开启,这个配置类便会向容器中加入StatViewServlet,并配置好默认参数。我们如果想自定义参数,可以再druid关键词下配置。默认允许本机进入,默认url-pattern是/druid/。
同理,WebStatFilter也需要我们开启,默认是关闭的。它帮我们配置好了过滤的urlpattren为"/",排除了druid的urlpattern与一些静态资源".js,.gif,.jpg,.png,.css,.ico,/druid/*"。
@ConditionalOnWebApplication
@ConditionalOnProperty(name = "spring.datasource.druid.web-stat-filter.enabled", havingValue = "true")
public class DruidWebStatFilterConfiguration {
@Bean
public FilterRegistrationBean webStatFilterRegistrationBean(DruidStatProperties properties) {
DruidStatProperties.WebStatFilter config = properties.getWebStatFilter();
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
WebStatFilter filter = new WebStatFilter();
registrationBean.setFilter(filter);
registrationBean.addUrlPatterns(config.getUrlPattern() != null ? config.getUrlPattern() : "/*");
registrationBean.addInitParameter("exclusions", config.getExclusions() != null ? config.getExclusions() : "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
if (config.getSessionStatEnable() != null) {
registrationBean.addInitParameter("sessionStatEnable", config.getSessionStatEnable());
}
if (config.getSessionStatMaxCount() != null) {
registrationBean.addInitParameter("sessionStatMaxCount", config.getSessionStatMaxCount());
}
if (config.getPrincipalSessionName() != null) {
registrationBean.addInitParameter("principalSessionName", config.getPrincipalSessionName());
}
if (config.getPrincipalCookieName() != null) {
registrationBean.addInitParameter("principalCookieName", config.getPrincipalCookieName());
}
if (config.getProfileEnable() != null) {
registrationBean.addInitParameter("profileEnable", config.getProfileEnable());
}
return registrationBean;
}
}
2、配置文件+自定义配置类
这种方法不使用框架给我们反射创建出的数据源,我们自己重新new一个数据源放在容器中,注册StatViewServlet与WebStatFilter进入容器,并附上初始化参数。采用配置类加上配置文件的配置方法。如果不使用druid-spring-boot-starter只导入druid依赖的话可以采用这种方法。
导入druid的maven依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.23</version>
</dependency>
先对配置文件进行配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
#SpringBoot因为默认是hikari数据源所以对于其他数据源默认是不注入这些属性的,需要手动配置
#druid数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 600000
# 主要配置以上几个即可
timeBetweenEvictionRunsMillis: 600000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入 此处配置不能遗漏服务sql监控台不能监控sql
#如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
#则导入 log4j 依赖即可,Maven 地址: https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
在config包下创建DruidConfig
@Configuration
public class DruidConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource getMyDruidDataSource(){
return new DruidDataSource();
}
//配置Druid的监控
//1.配置一个管理后台的Servlet
@Bean
public ServletRegistrationBean statViewServlet(){
// 记得加上"/druid/*",否则在进行登录页面的重定向过多而无法访问的问题(记得在Google浏览器才会报这个错)
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(),"/druid/*");
Map<String,String> initParams = new HashMap<>();
initParams.put("loginUsername","admin");
initParams.put("loginPassword","123456");
//默认是允许所有访问
//initParams.put("allow","");
// initParams.put("deny","192.168.31.30");
bean.setInitParameters(initParams);
return bean;
}
//2.配置一个web监控的filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String,String> initParams = new HashMap<>();
//配置拦截时需要排除的请求
initParams.put("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
个人博客地址: www.myblogs.site
.