1.JDBC+HikariDataSource
在SpringBoot 2.x項目中,預設使用Hikari連接配接池管理資料源。相比于傳統的 C3P0 、DBCP、Tomcat jdbc 等連接配接池更加優秀。
當項目pom.xml引入spring-boot-starter-jdbc啟動器依賴後,即可自動導入Hikari,該啟動器不但依賴它,還會對其自動配置并建立資料源。我們以MySQL資料庫為例,介紹如何使用Hikari。
資料源是啥?為什麼要用?怎麼用?
1.1應用執行個體
示範SpringBoot如何通過 JDBC+HikariDataSource 完成對Mysql操作。
(1)資料庫和表
-- 建立資料庫DROP DATABASE IF EXISTS spring_boot;CREATE DATABASE spring_boot;USE spring_boot; -- 建立表CREATE TABLE furn(`id` INT(11) PRIMARY KEY AUTO_INCREMENT, #id`name` VARCHAR(64) NOT NULL, #家居名`maker` VARCHAR(64) NOT NULL, #廠商`price` DECIMAL(11,2) NOT NULL, #價格`sales` INT(11) NOT NULL, #銷量`stock` INT(11) NOT NULL, #庫存`img_path` VARCHAR(256) NOT NULL #照片路徑); -- 初始化家居資料INSERT INTO furn(`id` , `name` , `maker` , `price` , `sales` , `stock` , `img_path`) VALUES(NULL , '北歐風格小桌子' , '熊貓家居' , 180 , 666 , 7 , 'assets/images/product-image/6.jpg'); INSERT INTO furn(`id` , `name` , `maker` , `price` , `sales` , `stock` , `img_path`) VALUES(NULL , '簡約風格小椅子' , '熊貓家居' , 180 , 666 , 7 , 'assets/images/product-image/4.jpg'); INSERT INTO furn(`id` , `name` , `maker` , `price` , `sales` , `stock` , `img_path`) VALUES(NULL , '典雅風格小台燈' , '螞蟻家居' , 180 , 666 , 7 , 'assets/images/product-image/14.jpg'); INSERT INTO furn(`id` , `name` , `maker` , `price` , `sales` , `stock` , `img_path`) VALUES(NULL , '溫馨風格盆景架' , '螞蟻家居' , 180 , 666 , 7 , 'assets/images/product-image/16.jpg'); SELECT * FROM furn;
(2)進行資料庫開發,首先要在pom.xml檔案中引入spring-boot-starter-data-jdbc。SpringBoot不知道項目要操作Mysql還是Oracle,是以還需要導入資料庫驅動,并指定對應版本。
<!--進行資料庫開發,引入data-jdbc starter--><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jdbc</artifactId></dependency> <!--導入mysql驅動,如果使用版本仲裁,SpringBoot預設的版本為8.0.26--><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version></dependency>
(3)在application.yml配置操作資料源的資訊
spring: datasource: #配置資料源 #說明:如果沒有配置useSSL=true,啟動項目會報紅警告,但不影響使用 url: jdbc:mysql://localhost:3306/spring_boot?useSSL=true&useUnicode=true&characterEncoding=UTF-8 username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver
(4)建立Javabean--Furn.java
package com.li.thymeleaf.bean; import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor; import java.math.BigDecimal; /** * @author 李 * @version 1.0 */@Data@NoArgsConstructor@AllArgsConstructorpublic class Furn { private Integer id; private String name; private String maker; private BigDecimal price; private Integer sales; private Integer stock; private String imgPath;}
(5)測試類ApplicationTests.java
package com.li.thymeleaf; import com.li.thymeleaf.bean.Furn;import org.junit.jupiter.api.Test;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate; import javax.annotation.Resource;import java.util.List; /** * @author 李 * @version 1.0 * 示範如何在SpringBoot中開發測試類 */@SpringBootTestpublic class ApplicationTests { //這裡使用spring的JDBCTemplate @Resource private JdbcTemplate jdbcTemplate; @Test public void contextLoads() { //使用RowMapper接口來對傳回的資料進行封裝(底層是反射->setter) BeanPropertyRowMapper<Furn> rowMapper = new BeanPropertyRowMapper<>(Furn.class); List<Furn> furns = jdbcTemplate.query("select * from furn", rowMapper); for (Furn furn : furns) { System.out.println("furn=" + furn); } //檢視底層使用的是什麼資料源 System.out.println(jdbcTemplate.getDataSource().getClass()); }}
測試結果:
<!--要開發SpringBoot測試類,需要引入test starter--><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId></dependency>
2.整合Druid到SpringBoot
2.1Druid介紹
alibaba/druid: 為監控而生的資料庫連接配接池 (github.com)
官方使用文檔 · alibaba/druid Wiki (github.com)
Druid資料庫連接配接池性能優秀,它除了提供性能卓越的資料池功能外,還繼承了SQL監控,黑名單攔截等功能。強大的監控特性,通過Druid提供的監控功能,可以清楚知道連接配接池和SQL的工作情況,是以根據項目需要,我們也要掌握Druid和SpringBoot的整合。
整合Druid到SpringBoot的方式:
- 自定義方式
- 引入starter
2.2Druid基本使用
(1)修改pom.xml,引入druid依賴
<!--引入druid依賴--><dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.17</version></dependency>
(2)建立配置類 DruidDataSourceConfig.java,将DruidDataSource注入容器
package com.li.thymeleaf.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; /** * @author 李 * @version 1.0 * 配置類 */@Configurationpublic class DruidDataSourceConfig { //注入DruidDataSource //通過@ConfigurationProperties指定讀取application.yml檔案的資料 //我們就不需要調用DruidDataSource的setXxx方法來配置(不推薦) @ConfigurationProperties("spring.datasource") @Bean public DataSource dataSource() { return new DruidDataSource(); }}
(3)測試類ApplicationTests.java(略,同上)
測試結果:
2.2.1一個問題
問題:為什麼我們注入了自己的資料源,預設的HikariDataSource就失效了?
先來弄明白,預設的HikariDataSource 是如何配置的:
SpringBoot通過DataSourceAutoConfiguration.java來進行資料源的配置,在進行預設的配置之前,如果檢測到容器中已經有DataSource Bean,就不會注入預設的HikariDataSource。
是以,如果你注入了自己的資料源,就不會注入預設的HikariDataSource。
DataSourceAutoConfiguration.java:
2.3Druid監控功能
2.3.1開啟内置監控頁
怎樣使用Druid的内置監控頁面:内置監控頁面是一個Servlet,具體配置看這裡
(1)在配置類中,啟用druid的監控頁功能:
在web項目中使用web.xml配置,若在SpringBoot中,有兩種方法注入Servlet---注解和RegistrationBean,這裡使用RegistrationBean
DruidDataSourceConfig.java:
package com.li.thymeleaf.config; import com.alibaba.druid.pool.DruidDataSource;import com.alibaba.druid.support.http.StatViewServlet;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.boot.web.servlet.ServletRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; /** * @author 李 * @version 1.0 * 配置類 */@Configurationpublic class DruidDataSourceConfig { //注入DruidDataSource //通過@ConfigurationProperties指定讀取yml檔案的字首的資料 @ConfigurationProperties("spring.datasource") @Bean public DataSource dataSource() { return new DruidDataSource(); } //配置Druid的監控頁功能 @Bean public ServletRegistrationBean statViewServlet() { //建立StatViewServlet ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); //設定初始化參數-使用者名和密碼-根據官方配置檔案設定 registrationBean.addInitParameter("loginUsername", "olien"); registrationBean.addInitParameter("loginPassword", "123456"); return registrationBean; }}
(2)啟動項目,浏覽器中通路http://項目ip:項目端口/項目名稱/druid/index.html,輸入配置的使用者名和密碼,即可通路到内置的監控頁面:
2.3.2SQL監控
配置_StatFilter · alibaba/druid Wiki (github.com)
除了文檔中的配置方式,也可在配置類中直接對資料源進行設定。
修改DruidDataSourceConfig.java:
啟用SQL監控功能之後,在監控頁中可以檢視到所有對資料庫發出的SQL語句:
2.3.3-Web關聯監控
Web關聯監控配置
Spring關聯監控配置
修改DruidDataSourceConfig.java:注入webStatFilter
//配置WebStatFilter,用于采集web-jdbc關聯的監控資料@Beanpublic FilterRegistrationBean webStatFilter() { //建立過濾器webStatFilter WebStatFilter webStatFilter = new WebStatFilter(); FilterRegistrationBean<WebStatFilter> filterRegistrationBean = new FilterRegistrationBean<>(webStatFilter); //設定webStatFilter的監控url filterRegistrationBean.setUrlPatterns(Arrays.asList("/*")); //根據官方文檔設定webStatFilter排除的url filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); return filterRegistrationBean;}
啟用URI監控功能之後,在監控頁中可以檢視到所有的Web應用情況和URI請求情況:
2.3.4SQL防火牆
Druid提供了WallFilter,它是基于SQL語義分析來實作防禦SQL注入攻擊的。具體配置看這裡
修改DruidDataSourceConfig.java:
啟用SQL防火牆之後,在監控頁中可以檢視到所有的SQL情況:
2.3.5Session監控
注意:這裡的Session不包括Druid背景監控系統産生的Session
Druid的Session監控不需要配置,在開啟了内置監控功能後就可以使用了。
2.4Druid-Starter
整合Druid到SpringBoot的方式有兩種:自定義方式和引入starter。
2.3中的所有例子中我們使用的是自己引入druid+配置類方式整合druid和監控。此外,還可以引入Druid Srping Boot Starter,讓程式員在SpringBoot項目中更加輕松內建Druid和監控。
示範使用Druid-Starter(示範之前,删除之前所有的自定義方式操作)
(1)pom.xml引入druid-spring-boot-starter
<!--引入druid的starter--><dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.17</version></dependency>
(2)在application.yml檔案中配置druid和監控功能
spring: datasource: #配置資料源 #如果沒有配置useSSL=true,啟動項目會報紅警告,但不影響使用 url: jdbc:mysql://localhost:3306/spring_boot?useSSL=true&useUnicode=true&characterEncoding=UTF-8 username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver #配置druid和監控功能 druid: stat-view-servlet: #(1)開啟監控頁 enabled: true login-username: jack login-password: 1234 reset-enable: false web-stat-filter: #(2)啟用web監控功能 enabled: true url-pattern: /* exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" filter: stat: #(3)啟用sql監控功能 slow-sql-millis: 1000 #機關ms log-slow-sql: true #啟用慢查詢的sql日志 enabled: true wall: #(4)啟用sql防火牆功能 enabled: true config: drop-table-allow: false #是否允許進行删除表的操作 select-all-column-allow: false #是否允許查詢所有字段的操作
3.練習
将異常處理、注入Servlet、Filter、Listener,Tomcat切換,資料庫操作(HikariDataSource&DruidDataSource)相關代碼和案例寫一遍