栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

03-03:Druid数据源

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

03-03:Druid数据源

Spring Boot 1.x版本默认使用的是tomcat.jdbc数据源,Sprng Boot 2.x版本默认使用的是Hikari数据源。如果使用其他数据源,还需要进行额外配置,比如阿里巴巴的Druid。

Druid是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等连接池的优点,同时加入了日志监控。Druid 可以很好的监控数据库池连接和 SQL 的执行情况,天生就是针对监控而生的 数据库连接池。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。

Github地址:https://github.com/alibaba/druid/
Apache地址:http://druid.apache.org/

我们以MySQL数据库为例,介绍如何使用Druid,如何实现数据库监控。


1、创建项目
  1. 在Idea中通过Spring Initializr方式,创建名称为springboot0303-druid的SpringBoot项目并加入如图所示依赖。本案例中Spring Boot的版本为2.4.11。

  1. 项目创建成功后,其pom.xml配置如下。Druid依赖spring-jdbc,spring-boot-starter-jdbc依赖spring-jdbc,spring-boot-starter-data-jpa依赖spring-boot-starter-jdbc,因此,Druid的最低依赖是spring-jdbc,具体配置可根据实际需要调整。


    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.4.11
         
    
    com.company
    springboot0303-druid
    0.0.1-SNAPSHOT
    springboot0303-druid
    Demo project for Spring Boot
    
        1.8
    
    

        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
            org.springframework.boot
            spring-boot-starter-data-jdbc
        

        
        
        
        

        
        
        
        
        

        
            mysql
            mysql-connector-java
            runtime
        
        
        
            org.projectlombok
            lombok
            true
        

    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            org.projectlombok
                            lombok
                        
                    
                
            
        
    



3.在pom.xml中加入Druid的启动器依赖。阿里巴巴为了迎合Spring Boot项目而适配的Druid数据源启动器,当在pom.xml文件中引入该启动器后,不需要再进行其他额外配置,Spring Boot项目会自动识别配置Druid数据源。


     com.alibaba
     druid-spring-boot-starter
     1.2.8

4.运行主启动程序Application,控制台日志中有一条警告信息,而且导致应用程序启动失败。

...
2021-10-12 01:24:43.277  WARN 19552 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class
2021-10-12 01:24:43.282  INFO 19552 --- [  restartedMain] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2021-10-12 01:24:43.295  INFO 19552 --- [  restartedMain] ConditionevaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-10-12 01:24:43.313 ERROR 19552 --- [  restartedMain] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class


Action:

Consider the following:
	If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
	If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).


Process finished with exit code 0

通过分析上述日志得知,应用程序在启动时,配置名称叫dataSource的数据源Bean失败,是因为其url属性未指定导致不能确定合适的驱动程序类,而且也无法配置嵌入式数据源。

2、全局配置

1.在全局配置文件application.properties中,增加spring.datasource.url配置。

spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?serverTimezone=UTC&useSSL=false

2.重新运行主启动程序Application,应用程序启动失败。根据控制台日志可知,容器已经创建dataSource数据源Bean,其类名为com.alibaba.druid.pool.DruidDataSource,并一直使用当前Windows用户名和空密码尝试创建连接,但是失败了。

...
2021-10-12 10:54:05.258 ERROR 20820 --- [eate-1941501166] com.alibaba.druid.pool.DruidDataSource   : create connection SQLException, url: jdbc:mysql://localhost:3306/springbootdata?serverTimezone=UTC&useSSL=false, errorCode 1045, state 28000

java.sql.SQLException: Access denied for user 'liuzh'@'localhost' (using password: NO)
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) ~[mysql-connector-java-8.0.26.jar:8.0.26]
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-java-8.0.26.jar:8.0.26]
	at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:828) ~[mysql-connector-java-8.0.26.jar:8.0.26]
	at com.mysql.cj.jdbc.ConnectionImpl.(ConnectionImpl.java:448) ~[mysql-connector-java-8.0.26.jar:8.0.26]
	at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241) ~[mysql-connector-java-8.0.26.jar:8.0.26]
	at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198) ~[mysql-connector-java-8.0.26.jar:8.0.26]
	at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1657) ~[druid-1.2.8.jar:1.2.8]
	at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1723) ~[druid-1.2.8.jar:1.2.8]
	at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2838) ~[druid-1.2.8.jar:1.2.8]


Process finished with exit code -1

3.在全局配置文件application.properties中,增加spring.datasource.username和spring.datasource.password配置。

spring.datasource.username=root
spring.datasource.password=123456

4.重新运行主启动程序Application,应用程序启动成功。

...
2021-10-12 11:01:32.207  INFO 11712 --- [  restartedMain] c.a.d.s.b.a.DruidDataSourceAutoConfigure : Init DruidDataSource
2021-10-12 11:01:32.309  INFO 11712 --- [  restartedMain] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
...

3、单元测试

1.在主启动程序单元测试类ApplicationTests中加入自动装配、显示dataSource信息的代码。

package com.company.project;

import com.alibaba.druid.pool.DruidDataSource;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.sql.DataSource;
import java.sql.SQLException;

@SpringBootTest
public class ApplicationTests {

    @Autowired
    private DataSource dataSource;

    @Test
    void contextLoads() {
    }

    @Test
    void showDataSource() {

        DruidDataSource druidDataSource = (DruidDataSource) dataSource;

        System.out.println("DataSource:" + druidDataSource);

        System.out.println("DataSourceClassName:" + druidDataSource.getClass().getName());
        try {
            System.out.println("Connection:" + druidDataSource.getConnection().toString());
            System.out.println("ConnectionIsClosed:" + druidDataSource.getConnection().isClosed());
            System.out.println("ConnectionIsReadOnly:" + druidDataSource.getConnection().isReadOnly());
            System.out.println("ConnectionAutoCommit:" + druidDataSource.getConnection().getAutoCommit());
            System.out.println("ConnectionTransactionIsolation:" + druidDataSource.getConnection().getTransactionIsolation());
            System.out.println("ConnectionNetworkTimeout:" + druidDataSource.getConnection().getNetworkTimeout());
            System.out.println("ConnectionClassName:" + druidDataSource.getConnection().getClass().getName());
            System.out.println("ConnectionCatalog:" + druidDataSource.getConnection().getCatalog());
            System.out.println("InitialSize:" + druidDataSource.getInitialSize());
            System.out.println("MinIdle:" + druidDataSource.getMinIdle());
            System.out.println("MaxIdle:" + druidDataSource.getMaxIdle());

            System.out.println("DataSource:" + dataSource);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

}

2.运行showDataSource()单元测试方法,执行成功。输出结果显示,初始化连接数量为1。

DataSource:{
	CreateTime:"2021-10-12 11:57:20",
	ActiveCount:0,
	PoolingCount:1,
	CreateCount:1,
	DestroyCount:0,
	CloseCount:1,
	ConnectCount:1,
	Connections:[
		{ID:1279556617, ConnectTime:"2021-10-12 11:57:22", UseCount:1, LastActiveTime:"2021-10-12 11:57:22"}
	]
}
DataSourceClassName:com.alibaba.druid.pool.DruidDataSource
Connection:com.mysql.cj.jdbc.ConnectionImpl@4c447c09
ConnectionIsClosed:false
ConnectionIsReadOnly:false
ConnectionAutoCommit:true
ConnectionTransactionIsolation:4
ConnectionNetworkTimeout:0
ConnectionClassName:com.alibaba.druid.pool.DruidPooledConnection
ConnectionCatalog:springbootdata
InitialSize:0
MinIdle:0
MaxIdle:8
DataSource:{
	CreateTime:"2021-10-12 11:57:20",
	ActiveCount:8,
	PoolingCount:0,
	CreateCount:8,
	DestroyCount:0,
	CloseCount:1,
	ConnectCount:9,
	Connections:[
	]
}



4、其它参数

Druid数据源启动器内部已经初始化了一些运行参数(例如initialSize. maxActive等),如果开发过程中需要修改其运行参数,则必须在全局配置文件中修改。

1.在全局配置文件application.properties中添加druid运行参数配置。

# 数据源Druid
# 数据源类型
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 初始化连接数
spring.datasource.initialSize=20
# 最小空闲数
spring.datasource.minIdle=10
# 最大连接数
spring.datasource.maxActive=100

添加上述配置后,会发现配置的initialSize、minIdle和maxActive属性底色为黄色(IDEA开发工具中的显示色),是因为在Spring Boot提供的数据源自动配置类org.springframework.boot.autoconfigure.jdbc.DataSourceProperties中,没有与这些参数对应的默认属性,所以这些设置的属性值无法识别和生效。因此需要编写一个自定义配置类,将配置文件中的属性注入到Druid数据源属性中。

2.在com.company.project.config包下创建一个DataSourceConfig自定义配置类对Druid数据源属性值进行注入。

package com.company.project.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource getDruid() {
        return new DruidDataSource();
    }
}

3.重新运行ApplicationTests类中的showDataSource()单元测试方法,执行成功。查看日志可知,初始化连接数为20,最后一次执行后的初始化连接数为12。

DataSource:{
	CreateTime:"2021-10-12 11:55:14",
	ActiveCount:0,
	PoolingCount:20,
	CreateCount:20,
	DestroyCount:0,
	CloseCount:1,
	ConnectCount:1,
	Connections:[
		{ID:1789376127, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1808547623, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:2041504298, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:915540950, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1632716597, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1810790719, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1700751834, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1135936028, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:674667952, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:814300680, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:780566650, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1162400340, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1494158416, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:546242567, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:982565180, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:969502280, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:411408557, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1087519874, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:2096598149, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:247334525, ConnectTime:"2021-10-12 11:55:16", UseCount:1, LastActiveTime:"2021-10-12 11:55:16"}
	]
}
DataSourceClassName:com.alibaba.druid.pool.DruidDataSource
Connection:com.mysql.cj.jdbc.ConnectionImpl@ebe067d
ConnectionIsClosed:false
ConnectionIsReadOnly:false
ConnectionAutoCommit:true
ConnectionTransactionIsolation:4
ConnectionNetworkTimeout:0
ConnectionClassName:com.alibaba.druid.pool.DruidPooledConnection
ConnectionCatalog:springbootdata
InitialSize:20
MinIdle:10
MaxIdle:8
DataSource:{
	CreateTime:"2021-10-12 11:55:14",
	ActiveCount:8,
	PoolingCount:12,
	CreateCount:20,
	DestroyCount:0,
	CloseCount:1,
	ConnectCount:9,
	Connections:[
		{ID:1789376127, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1808547623, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:2041504298, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:915540950, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1632716597, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1810790719, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1700751834, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1135936028, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:674667952, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:814300680, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:780566650, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"},
		{ID:1162400340, ConnectTime:"2021-10-12 11:55:16", UseCount:0, LastActiveTime:"2021-10-12 11:55:16"}
	]
}


5、数据源监控

Druid数据源具有监控的功能,并提供了一个 web 界面方便用户查看和操作。但是,需要设置Druid的后台管理页面,比如登录账号、密码等。

1.在DataSourceConfig类中,增加监控管理后台的Servlet和web监控的filter。

package com.company.project.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
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.sql.DataSource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource getDruid() {
        return new DruidDataSource();
    }

    //配置 Druid 监控管理后台的Servlet;
    //内置 Servlet 容器时没有web.xml文件,所以使用 Spring Boot 的注册 Servlet 方式
    @Bean
    public ServletRegistrationBean statViewServlet(){
        ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        // 这些参数可以在 com.alibaba.druid.support.http.StatViewServlet 的父类 com.alibaba.druid.support.http.ResourceServlet 中找到
        Map initParams = new HashMap<>();

        initParams.put("loginUsername","admin");
        initParams.put("loginPassword","123456");
        initParams.put("allow",""); //默认就是允许所有访问

        //deny:Druid 后台拒绝谁访问,表示禁止此ip访问
        // initParams.put("deny","192.168.10.132");
        bean.setInitParameters(initParams);
        return bean;
    }


    //2、配置一个web监控的filter
    @Bean
    public FilterRegistrationBean webStatFilter(){
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());

        Map initParams = new HashMap<>();
        initParams.put("exclusions","*.js,*.css,/druid/*");

        bean.setInitParameters(initParams);

        bean.setUrlPatterns(Arrays.asList("/*"));

        return  bean;
    }

}

2.重新运行主启动类Application成功后,使用浏览器访问http://localhost:8080/druid地址,在登录界面输入用户名和密码并点击登录按钮。

3.紧接着,就可以看到Druid监控的首页了。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/317992.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号