1、Druid简介
Druid是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。
2、Druid功能
1、替换DBCP和C3P0。Druid提供了一个高效、功能强大、可扩展性好的数据库连接池。 2、可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能有帮助。 3、数据库密码加密。直接把数据库密码写在配置文件中,这是不好的行为,容易导致安全问题。DruidDruiver和DruidDataSource都支持PasswordCallback。 4、SQL执行日志,Druid提供了不同的LogFilter,能够支持Common-Logging、Log4j和JdkLog,你可以按需要选择相应的LogFilter,监控你应用的数据库访问情况。 5、扩展JDBC,如果你要对JDBC层有编程的需求,可以通过Druid提供的Filter机制,很方便编写JDBC层的扩展插件。
3、Druid常用配置
4、SpringBoot整合Druid简单入门程序
环境搭建
4.1、导入依赖
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.5</version>
</dependency>
<!--validation验证校验-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!--引入lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--引入web启动-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<!--引入mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--引入连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
</dependencies>
4.2、配置文件application.yaml
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
# Spring Boot 默认是不注入这些属性值的,需要自己绑定
# druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御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
4.3、导入log4j.properties日志配置
log4j.rootLogger=DEBUG, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
4.4、数据库表结构
4.5、contoller
package cn.gorit.controller;
import cn.gorit.mapper.map1.BookMapper1;
import cn.gorit.mapper.map2.BookMapper2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class JDBCController {
@Autowired
JdbcTemplate jdbcTemplate;
@RequestMapping("/user/select")
public List<Map<String, Object>> selectAll(){
String sql = "select * from user";
List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
return maps;
}
@RequestMapping("/user/insert")
public String insertUser(){
String sql = "insert into user(id,username,birthday,sex,address) values(?,?,?,?,?)";
jdbcTemplate.update(sql,58,"张三", "2020/11/11","男","成都");
return "insert_ok";
}
@RequestMapping("/user/delete/{id}")
public String deleteId(@PathVariable("id") Integer id){
String sql = "delete from user where id="+id;
jdbcTemplate.update(sql);
return "delete_ok";
}
}
4.6、测试
5、SpringBoot整合Druid之日志监控与请求拦截
config
package com.weinigg.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.beans.factory.annotation.Configurable;
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 javax.servlet.Filter;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DruidConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DruidDataSource getDataSource(){
DruidDataSource dataSource = new DruidDataSource();
return dataSource;
}
/**
* 日志监控
* @return
*/
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean registration = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String, String> maps = new HashMap<String, String>();
//日志监控的用户名密码
maps.put("loginUsername", "admin");
maps.put("loginPassword", "1234");
//允许访问
maps.put("allow", "");
//maps.put("主机名","主机地址");禁止访问
registration.setInitParameters(maps);
return registration;
}
/**
* 拦截器
* @return
*/
@Bean
public FilterRegistrationBean statViewFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean(new WebStatFilter());
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("exclusions","*.js,*.css,/druid/*");
//不统计哪些请求
bean.setInitParameters(initParameters);
return bean;
}
}
6、DruidUtil工具类:
package Util;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
public class DruidUtil {
private static DataSource ds;
static {
//加载配置文件和建立连接池
try {
Properties pro = new Properties();
InputStream resourceAsStream = DruidUtil.class.getClassLoader().getResourceAsStream("Druid.properties");
pro.load(resourceAsStream);
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接池
* @return
*/
public static DataSource getDataSource(){
return ds;
}
/**
* 获取连接池中的一个连接
* @return
* @throws SQLException
*/
public Connection getconnection() throws SQLException {
return ds.getConnection();
}
/**
* 关闭数据库的资源 三个对象都存在时
* @param conn
* @param res
* @param pstmt
*/
public static void close(Connection conn, ResultSet res, PreparedStatement pstmt){
if (conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (res!=null){
try {
res.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (pstmt!=null){
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 关闭数据库的连接(只存在Connection和PreparedStatement对象时)
* @param conn
* @param pstmt
*/
public void close(Connection conn,PreparedStatement pstmt){
if (conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (pstmt!=null){
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
7、示例测试
登录,进入后台监控页面
运行SQL
Druid后台监控
8、总结
对于一个简单的数据库应用,可以简单地在需要访问数据库时,就新创建一个连接,用完后就关闭它。但是对于一个复杂的数据库应用,频繁的建立、关闭连接,会极大的减低系统的性能,因为对于连接的使用成了系统性能的瓶颈,数据库连接池就是为了解决这个问题。 外部使用者可通过getConnection 方法获取连接,使用完毕后再通过releaseConnection方法将连接返回,注意此时连接并没有关闭,而是由连接池管理器回收,并为下一次使用做好准备。 数据库连接池的好处:
Druid是Java语言中最好的数据库连接池,Druid能够提供强大的监控和扩展功能,是一个可用于大数据实时查询和分析的高容错、高性能的开源分布式系统,尤其是当发生代码部署、机器故障以及其他产品系统遇到宕机等情况时,Druid仍能够保持100%正常运行。主要特色:为分析监控设计;快速的交互式查询;高可用;可扩展。