Springcloud学习笔记41--DataSource数据源,Springboot整合Druid数据库连接池;Springboot自动读取yml文件中的配置,解析为bean并注入spring容器中
0 DataSource接口
最早的时候,程序员连接数据库还是这么个操作;
可以清楚的看到,曾经获取数据库连接的代码还需要使用 DriverManager,大家都清楚,DriverManager#getConnection
是通过数据库驱动直接与数据库建立连接
而建立数据库连接属于耗费时间的事情,如果业务层每次进行 SQL 查询都使用此方式,将会产生较大的系统开销;
一般系统的性能要求,单次请求需要稳定在 200 ms。经过在本地环境测试,DriverManager 形式创建数据库连接需要 300~500 ms 左右;
0.1 连接池的出现
存放数据库连接的池化技术,叫做 连接池。应用程序从连接池中获取数据库连接,使用过再放到池子里,是不是感觉很 Nice?完美的解决了重复创建消耗资源的情况
看似完美的背后,其实还存在一个致命的问题,那就是最开始去连接池中获取连接时,连接池中是没有连接的,还需要走创建流程
连接池是怎么解决这一问题呢?通过创建连接池时初始化其中的连接,一般连接池都有这样一个参数 initialSize,代表池子中初始化的连接数量
下图是 Druid 在执行 init 方法时数据库连接初始化的流程,当初始化连接小于池内连接时,进行循环创建,直到池内连接满足初始化数量
0.2 数据源登场
连接池虽然很牛,但是独木难支,连接池没有产生连接的能力,所以还需要配合类似 DriverManager 组件与数据库驱动配合创建连接。如果这样放到业务代码里,那岂不是还得封装一层?
这个时候,不约而同的想到一个公司,sun 公司是干啥的?制定规范的对不对,他们在 jdbc 2.0 版本推出一个 DataSource 的东东,用来进行规范约束,相当于把 DriverManager 和连接池概念揉合在一起,如果你想获取数据库连接,你通过我 DataSource 获取,你不用关心连接池和数据库连接怎么创建的,用就完了。
jdbc 2.0 版本推出 DataSource 之后,典型的像 DruidDataSource 就没有依赖 DriverManager,而是在自己实现类中调用了数据库驱动。这里只是重点强调,数据库连接不一定是使用 DriverManager 创建
总结下,数据源(DataSource)是 sun 公司指定用于获取数据库连接的规范接口,应用程序与数据库连接抽象的中间层,它存在于 javax.sql 包,用来代替 DriverManager 的方式获取数据库连接;
1 Druid概述
Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控。
1.1 maven依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.24</version> </dependency> <!--druid-spring-boot-starter只是在druid基础上进行了一次封装,专门用来整合spring-boot项目--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.24</version> </dependency>
1.2 配置druid 数据源专有配置 application.yml
spring: datasource: type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://localhost:3306/day001?serverTimezone=Asia/Shanghai&useSSL=false username: root password: 888888 driver-class-name: com.mysql.cj.jdbc.Driver #druid连接池配置 druid: #初始化连接大小 initial-size: 5 #最大连接池数量 max-active: 20 #最小连接池数量 min-idle: 3 #配置获取连接等待超时时间,单位毫秒 max-wait: 60000 #配置间隔多久才进行一次检查看,检查需要关闭的空闲连接,单位毫秒 time-between-eviction-runs-millis: 60000 #配置一个连接在池中最小的生存时间,单位毫秒 min-evictable-idle-time-millis: 300000 validation-query: select 'x' #建议配置为true,不影响性能,并且保证安全性,申请连接的时候检测 test-while-idle: true #获取连接时执行检测,建议关闭,影响性能 test-on-borrow: false #归还连接时执行检测,建议关闭,影响性能 test-on-return: false #检测连接是否有效的超时时间 validation-query-timeout: 10
1.3 @Configuration、@ConfigurationProperties、@EnableConfigurationProperties、@Bean
1.3.1 @Configuration
@Configuration与@Bean结合使用。@Configuration可理解为用spring的时候xml里面的<beans>标签,@Bean可理解为用spring的时候xml里面的<bean>标签。Spring Boot不是spring的加强版,所以@Configuration和@Bean同样可以用在普通的spring项目中,而不是Spring Boot特有的,只是在spring用的时候,注意加上扫包配置。
在@Configuration中被@Bean标记的方法,会被Spring进行CGLIB代理,从而进行增强。来看一下Spring中的相关源代码实现。
@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
- @Configuration配置spring并启动spring容器
- @Configuration启动容器+@Bean注册Bean
- @Configuration启动容器+@Component注册Bean
使用 AnnotationConfigApplicationContext 注册 AppContext 类的两种方法
配置Web应用程序(web.xml中配置AnnotationConfigApplicationContext)
1.3.2 @Component和@Bean注解
@Component注解表明一个类会作为组件类,并告知Spring要为这个类创建bean。
@Bean注解告诉Spring这个方法将会返回一个对象,这个对象要注册为Spring应用上下文中的bean。通常方法体中包含了最终产生bean实例的逻辑。
两者的目的是一样的,都是注册bean到Spring容器中。
1.3.3 @ConfigurationProperties
有时候有这样子的情景,我们想把配置文件的信息,读取并自动封装成实体类,这样子,我们在代码里面使用就轻松方便多了,这时候,我们就可以使用@ConfigurationProperties,它可以把同类的配置信息自动封装成实体类。
1.3.4 @EnableConfigurationProperties
@EnableConfigurationProperties注解的作用是:使使用 @ConfigurationProperties 注解的类生效。
2.Springboot自动读取yml文件中的配置,解析为bean并注入spring容器中
2.1 读取yml文件中的参数
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "spring.datasource.druid") @Data public class DataSourceProperties { private String driverClassName; private String url; private String username; private String password; }
2.2 编写配置类
@Configuration @Slf4j @EnableConfigurationProperties({DataSourceProperties.class}) public class DruidConfig { @Autowired DataSourceProperties dataSourceProperties; @Bean public DataSource druidDataSource(){ DruidDataSource druidDataSource=new DruidDataSource(); druidDataSource.setDriverClassName(dataSourceProperties.getDriverClassName()); druidDataSource.setUrl(dataSourceProperties.getUrl()); druidDataSource.setUsername(dataSourceProperties.getUsername()); druidDataSource.setPassword(dataSourceProperties.getPassword()); return druidDataSource; } }
通过debug模式可以看到数据绑定成功
3.使用案例2
3.1 编写配置类
package com.hzbank.flep.config; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import com.hzbank.flep.env.DataSourceProperties; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; 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 @Slf4j //@EnableConfigurationProperties({DataSourceProperties.class}) public class DruidConfig { /* 将自定义的 Druid数据源添加到容器中,不再让 Spring Boot 自动创建 绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource从而让它们生效 @ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中 前缀为 spring.datasource的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中 */ @ConfigurationProperties(prefix = "spring.datasource.druid") @Bean public DataSource druidDataSource() { return new DruidDataSource(); } //配置Druid的监控 //1、配置一个管理后台的Servlet @Bean public ServletRegistrationBean statViewServlet(){ ServletRegistrationBean 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("allow", "localhost"):表示只有本机可以访问 initParams.put("deny",""); //设置初始化参数 bean.setInitParameters(initParams); return bean; } //2、配置一个web监控的filter //配置 Druid 监控 之 web 监控的 filter //WebStatFilter:用于配置Web和Druid数据源之间的管理关联监控统计 @Bean public FilterRegistrationBean webStatFilter(){ FilterRegistrationBean bean = new FilterRegistrationBean(); bean.setFilter(new WebStatFilter()); //exclusions:设置哪些请求进行过滤排除掉,从而不进行统计 Map<String,String> initParams = new HashMap<>(); initParams.put("exclusions","*.js,*.css,/druid/*"); bean.setInitParameters(initParams); //"/*" 表示过滤所有请求 bean.setUrlPatterns(Arrays.asList("/*")); return bean; } }
编写完之后我们启动项目,访问http://localhost:7010/druid/login.html
就会到Druid的监控登录界面
利用postman发送请求新增一条记录(注意:一定要完成一次sql请求),此时Druid监控页面
参考文献:https://blog.csdn.net/weixin_45627031/article/details/108111017
https://machen.blog.csdn.net/article/details/120252496
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步