文末看往期系列教程:给个关注可好?
🌲 SpringData简介
对于数据访问层,无论是 SQL (关系型数据库) 还是 NoSql (非关系型数据库),Spring Boot 底层都是采用 Spring Data 的方式进行统一处理。
Spring Boot 底层都是采用 Spring Data 的方式进行统一处理各种数据库,Spring Data 也是 Spring 中与 Spring Boot、Spring Cloud 等齐名的知名项目。
Sping Data 官网: Spring Data
🌲 整合Druid数据源
🌾 Druid简介
Java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,又不得不使用数据库连接池。Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控。
Druid 可以很好的监控 DB 池连接和 SQL 的执行情况,天生就是针对监控而生的 DB 连接池。Druid 已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。
Spring Boot 2.0 以上默认使用 Hikari 数据源,可以说 Hikari 与 Driud 都是当前 Java Web 上最优秀的数据源,我们来重点介绍 Spring Boot 如何集成 Druid 数据源,如何实现数据库监控。
Druid Github地址:https://github.com/alibaba/druid/
|-------------------------------------------|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 配置 | 缺省值 | 说明 |
| name | | 配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。如果没有配置,将会生成一个名字,格式是:"DataSource-" + System.identityHashCode(this). 另外配置此属性至少在1.0.5版本中是不起作用的,强行设置name会出错。详情-点此处 。 |
| url | | 连接数据库的url,不同数据库不一样。例如: mysql : jdbc:mysql://10.20.153.104:3306/druid2 oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto |
| username | | 连接数据库的用户名 |
| password | | 连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里 |
| driverClassName | 根据url自动识别 | 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName |
| initialSize | 0 | 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 |
| maxActive | 8 | 最大连接池数量 |
| maxIdle | 8 | 已经不再使用,配置了也没效果 |
| minIdle | | 最小连接池数量 |
| maxWait | | 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。 |
| poolPreparedStatements | false | 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。 |
| maxPoolPreparedStatementPerConnectionSize | -1 | 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100 |
| validationQuery | | 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。 |
| validationQueryTimeout | | 单位:秒,检测连接是否有效的超时时间。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法 |
| testOnBorrow | true | 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 |
| testOnReturn | false | 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 |
| testWhileIdle | false | 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 |
| keepAlive | false (1.0.28) | 连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。 |
| timeBetweenEvictionRunsMillis | 1分钟(1.0.14) | 有两个含义: 1) Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。 2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明 |
| numTestsPerEvictionRun | 30分钟(1.0.14) | 不再使用,一个DruidDataSource只支持一个EvictionRun |
| minEvictableIdleTimeMillis | | 连接保持空闲而不被驱逐的最小时间 |
| connectionInitSqls | | 物理连接初始化的时候执行的sql |
| exceptionSorter | 根据dbType自动识别 | 当数据库抛出一些不可恢复的异常时,抛弃连接 |
| filters | | 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 监控统计用的filter:stat 日志用的filter:log4j 防御sql注入的filter:wall |
| proxyFilters | | 类型是List<com.alibaba.druid.filter.Filter>,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系 |
🌾 配置Druid
🍁 环境准备
- 创建新模块,选择Spring Initializr:
- 配置好项目的基础信息:
- 选择当前模块所需要使用到的技术集(Spring web ,Mybatis,Mysql)
- 在pom文件中添加druid相关依赖
XML
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
pom.xml 文件内容如下:
XML
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
</dependencies>
🍁 配置文件
我们需要在配置文件里面配置连接数据库的相关信息,比如:
XML
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/study?characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-active=20
spring.datasource.druid.max-wait=60000
spring.datasource.druid.time-between-eviction-runs-millis=60000
spring.datasource.druid.min-evictable-idle-time-millis=300000
spring.datasource.druid.test-while-idle=true
#durid monitor(过滤器,wall表示防火墙)
spring.datasource.druid.filters=stat,wall,slf4j
# 对所有的请求进行过滤
spring.datasource.druid.web-stat-filter.url-pattern=/*
# 排除一些不必要的过滤文件
spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*
#druid servlet(开启数据监控)
spring.datasource.druid.stat-view-servlet.enabled=true
# 配置数据监控控制台访问地址:localhost:8080/druid/index.html
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
# 是否允许重置
spring.datasource.druid.stat-view-servlet.reset-enable=false
# 开启慢sql写入日志功能
spring.datasource.druid.filter.stat.log-slow-sql=true
# 当sql语句执行超过1秒钟时写入日志
spring.datasource.druid.filter.stat.slow-sql-millis=1000
# 配置登录控制台的账号和密码
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=123456
🌲 整合Mybatis
🌾 导入依赖
整合Mybatis时,需要添加以下依赖:
XML
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
前面新建项目的时候我们已经勾选过mybatis framework,会帮我们自动添加整合mybatis的依赖,此处无需再引入。
这个依赖包下包含了mybatis依赖,Spring整合mybatis的依赖,Springboot相关的依赖
🌾 搭建项目环境
在项目中建立好相关的包环境
🌾 配置Mybatis
在application.yml中添加mybatis相关配置
mybatis.type-aliases-package=com.moxuan.demo.entity
mybatis.mapper-locations=classpath:mappers/*.xml
上面的配置中:
- mapper-locations: classpath:mappers/*.xml,表示我们会将mybatis的映射文件放入到resources下的mappers目录中。
- type-aliases-package: com.moxuan.demo.entity,表示我们会将实体类放入到这个配置的包中,这样在映射文件中使用实体类时可以无需再写这个包名。
🌲 测试准备
🌿 数据库脚本
sql
DROP TABLE IF EXISTS `hero`;
CREATE TABLE `hero` (
`id` int NOT NULL AUTO_INCREMENT,
`hname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`job` varchar(255) DEFAULT NULL,
`level` int DEFAULT NULL,
`sex` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb3;
-- ----------------------------
-- Records of hero
-- ----------------------------
INSERT INTO `hero` VALUES ('1', '夏侯惇', '战士', '2', '男');
INSERT INTO `hero` VALUES ('3', '甄姬', '法师', '2', '女');
INSERT INTO `hero` VALUES ('4', '安琪拉', '法师', '3', '女');
INSERT INTO `hero` VALUES ('5', '廉颇', '辅助', '1', '男');
INSERT INTO `hero` VALUES ('6', '张飞', '辅助', '1', '男');
INSERT INTO `hero` VALUES ('7', '后羿', '射手', '3', '男');
INSERT INTO `hero` VALUES ('8', '虞姬', '射手', '3', '女');
INSERT INTO `hero` VALUES ('9', '阿珂', '刺客', '3', '女');
INSERT INTO `hero` VALUES ('10', '孙悟空', '刺客', '3', '男');
INSERT INTO `hero` VALUES ('12', '王昭君', '法师', '3', '女');
INSERT INTO `hero` VALUES ('13', '王昭君', '法师', '3', '女');
INSERT INTO `hero` VALUES ('15', '花木兰', '战士', '12', '女');
🌿 实体类
java
package com.moxuan.boot_04_mybatis.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Hero {
private Integer id;
private String hname;
private String job;
private Integer level;
private String sex;
}
🌿 定义dao接口
- 编写dao映射器接口:
java
package com.moxuan.boot_04_mybatis.dao;
import com.moxuan.boot_04_mybatis.entity.Hero;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
public interface HeroDao {
@Select("select * from hero")
List<Hero> findAllHeros();
}
Repository和Mapper的本质区别在于它们实现持久化数据访问的方式不同。Repository基于ORM框架封装了一些常用的CRUD操作和查询方法,使用方便;Mapper基于注解或XML配置,提供了更细粒度的SQL控制能力,更加灵活。
此外,Repository和Mapper的接口定义和实现方式也不同。Repository是一个接口,继承JpaRepository或其他Repository接口,Spring Data会动态生成它的实现类;Mapper则是一个Java类,使用@Mapper注解后,MyBatis会基于注解或XML配置生成和维护它的实现类。
🌿编写业务层
- 封装业务层返回数据Result类
java
package com.moxuan.boot_04_mybatis.config;
import lombok.Data;
/**
* Created with IntelliJ IDEA.
*
* @Author: moxuan
* @Date: 2023/08
* @Description: 对返回数据进行统一封装
*/
@Data
public class Result {
private int code;// 状态码
private String msg;// 消息
private Object data;// 数据源
public static final int SUCCESS_CODE=200;
public static final int ERROR_CODE=-1;
public static final String SUCCESS_MSG="请求成功";
public static final String ERROR_MSG="请求失败";
public static Result success(){
Result result = new Result();
result.setCode(SUCCESS_CODE);
result.setMsg(SUCCESS_MSG);
return result;
}
public static Result error(){
Result result = new Result();
result.setCode(ERROR_CODE);
result.setMsg(ERROR_MSG);
return result;
}
public static Result sendResult(int code ,String msg){
Result result = new Result();
result.setMsg(msg);
result.setCode(code);
return result;
}
public static Result sendResult(int code ,String msg,Object obj){
Result result = new Result();
result.setData(obj);
result.setMsg(msg);
result.setCode(code);
return result;
}
}
- 业务层接口
java
package com.moxuan.boot_04_mybatis.service;
import com.moxuan.boot_04_mybatis.config.Result;
import com.moxuan.boot_04_mybatis.entity.Hero;
public interface HeroService {
Result getAllHeros();
}
- 业务层接口实现类
java
package com.moxuan.boot_04_mybatis.service.impl;
import com.moxuan.boot_04_mybatis.config.Result;
import com.moxuan.boot_04_mybatis.dao.HeroDao;
import com.moxuan.boot_04_mybatis.entity.Hero;
import com.moxuan.boot_04_mybatis.service.HeroService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class HeroServiceImpl implements HeroService {
@Autowired
private HeroDao dao;
@Override
public Result getAllHeros() {
List<Hero> heroList = dao.findAllHeros();
if (heroList.size()==0){
return Result.sendResult(Result.ERROR_CODE,"未查询到数据");
}
return Result.sendResult(Result.SUCCESS_CODE,"操作成功",heroList);
}
}
🌿编写测试类
java
package com.moxuan.boot_04_mybatis;
import com.moxuan.boot_04_mybatis.config.Result;
import com.moxuan.boot_04_mybatis.service.HeroService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Boot04MybatisApplicationTests {
@Autowired
HeroService heroService;
@Test
public void test(){
Result result = heroService.getAllHeros();
System.out.println(result);
}
}
🌲 启动Druid监控控制台
这里需要注意的是,Druid监控控制台,截至笔者编写本教程时,仅支持SpringBoot2.x版本,SpringBoot3.x版本需要待Druid相应版本更新后才能使用。
- 在前面的案例中,我们其实已经添加过启动控制台的配置,配置信息如下:
bash
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/study?characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-active=20
spring.datasource.druid.max-wait=60000
spring.datasource.druid.time-between-eviction-runs-millis=60000
spring.datasource.druid.min-evictable-idle-time-millis=300000
spring.datasource.druid.test-while-idle=true
#durid monitor(过滤器,wall表示防火墙)
spring.datasource.druid.filters=stat,wall,slf4j
# 对所有的请求进行过滤
spring.datasource.druid.web-stat-filter.url-pattern=/*
# 排除一些不必要的过滤文件
spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*
#druid servlet(开启数据监控)
spring.datasource.druid.stat-view-servlet.enabled=true
# 配置数据监控控制台访问地址:localhost:8080/druid/index.html
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
# 是否允许重置
spring.datasource.druid.stat-view-servlet.reset-enable=false
# 开启慢sql写入日志功能
spring.datasource.druid.filter.stat.log-slow-sql=true
# 当sql语句执行超过1秒钟时写入日志
spring.datasource.druid.filter.stat.slow-sql-millis=1000
# 配置登录控制台的账号和密码
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=123456
# mybatis相关配置
mybatis.type-aliases-package=com.moxuan.demo.entity
mybatis.mapper-locations=classpath:mappers/*.xml
- 启动程序,在地址栏输入:http://localhost:8080/druid/
- 进入登录界面后,此时输入在配置文件配置的用户名admin和密码123456,即可打开主页
- 编写控制器类进行测试
java
package com.moxuan.demo.controller;
import com.moxuan.demo.config.Result;
import com.moxuan.demo.service.HeroService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class WebController {
@Autowired
HeroService service;
@RequestMapping("heros")
public Result getAllHeros(){
Result result =service.getAllHeros();
return result;
}
}
- 启动程序,打开浏览器输入如下地址:
- 进入druid控制台,点击SQL监控,可以查看监控信息
都到这里了:动动手点个关注呗!!^_^
往期系列专题文章:
【SpringBoot详细教程】-01-SpringBoot入门【持续更新】-CSDN博客
【SpringBoot详细教程】-02-SpringBoot配置【持续更新】-CSDN博客