框架分析
大约 8 分钟
数据库编程
单体项目单数据源-HikariCP
1.
mysqlJ : '8.0.33', // MySQL驱动的版本
druid : '1.2.21', // Druid版本
springJdbc : '5.3.31', // SpringJDBC版本
HikariCP : '5.1.0', // 数据连接池
// 以下的配置为数据库开发所需要的依赖:
'mysql-connector-j' : "com.mysql:mysql-connector-j:${versions.mysqlJ}",
'druid-spring-boot-starter' : "com.alibaba:druid-spring-boot-starter:${versions.druid}",
'spring-jdbc' : "org.springframework:spring-jdbc:${versions.springJdbc}",
'druid' : "com.alibaba:druid:${versions.druid}",
'HikariCP' : "com.zaxxer:HikariCP:${versions.HikariCP}",
implementation(libraries.'mysql-connector-j')
implementation(libraries.'HikariCP')
implementation(libraries.'spring-jdbc')
2.
yix.database.driverClassName=com.mysql.cj.jdbc.Driver
yix.database.jdbcUrl=jdbc:mysql://192.168.16.8:3306/yootk
yix.database.username=root
yix.database.password=root
yix.database.connectionTimeOut=3000
yix.database.readOnly=false
yix.database.pool.idleTimeOut=3000
yix.database.pool.maxLifetime=60000
yix.database.pool.maximumPoolSize=60
yix.database.pool.minimumIdle=20
3.
package com.yix.config;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
/**
* @author wangdx
*/
@Configuration // 配置类
@PropertySource("classpath:config/database.properties") // 配置加载
public class DataSourceConfig {
@Value("${yix.database.driverClassName}") // 资源文件读取配置项
private String driverClassName; // 数据库驱动程序
@Value("${yix.database.jdbcUrl}") // 资源文件读取配置项
private String jdbcUrl; // 数据库连接地址
@Value("${yix.database.username}") // 资源文件读取配置项
private String username; // 用户名
@Value("${yix.database.password}") // 资源文件读取配置项
private String password; // 密码
@Value("${yix.database.connectionTimeOut}") // 资源文件读取配置项
private long connectionTimeout; // 连接超时
@Value("${yix.database.readOnly}") // 资源文件读取配置项
private boolean readOnly; // 只读配置
@Value("${yix.database.pool.idleTimeOut}") // 资源文件读取配置项
private long idleTimeout; // 连接最小维持时长
@Value("${yix.database.pool.maxLifetime}") // 资源文件读取配置项
private long maxLifetime; // 连接最大存活时长
@Value("${yix.database.pool.maximumPoolSize}") // 资源文件读取配置项
private int maximumPoolSize; // 连接池最大维持数量
@Value("${yix.database.pool.minimumIdle}") // 资源文件读取配置项
private int minimumIdle; // 连接池最小维持数量
@Bean("dataSource") // Bean注册
public DataSource dataSource() { // 配置数据源
HikariDataSource dataSource = new HikariDataSource(); // DataSource子类实例化
dataSource.setDriverClassName(this.driverClassName); // 驱动程序
dataSource.setJdbcUrl(this.jdbcUrl); // JDBC连接地址
dataSource.setUsername(this.username); // 用户名
dataSource.setPassword(this.password); // 密码
dataSource.setConnectionTimeout(this.connectionTimeout); // 连接超时
dataSource.setReadOnly(this.readOnly); // 是否为只读数据库
dataSource.setIdleTimeout(this.idleTimeout); // 最小维持时间
dataSource.setMaxLifetime(this.maxLifetime); // 连接的最大时长
dataSource.setMaximumPoolSize(this.maximumPoolSize); // 连接池最大容量
dataSource.setMinimumIdle(this.minimumIdle); // 最小维持连接量
return dataSource; // 返回Bean实例
}
}
4.
@ExtendWith(SpringExtension.class) // 使用JUnit5测试工具
@WebAppConfiguration // 启动WEB运行环境
@SpringBootTest(classes = DruidApplication.class) // 配置程序启动类
public class TestDruidDataSource {
@Autowired
private DataSource dataSource;
@Test
public void testDruid() { // 进行响应测试
try {
System.out.println(this.dataSource.getConnection());
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
单体项目单数据源-druid
1.
2.
spring:
yix: # 一个自定义配置项,这个名称就是数据库的名称
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 配置数据源的类型
driver-class-name: com.mysql.cj.jdbc.Driver # MySQL8之后的驱动
url: jdbc:mysql://192.168.16.8:3306/yootk # 数据库的JDBC连接地址
username: root # 用户名
password: root # 密码
druid: # 定义数据库连接池所需要的相关配置项
initial-size: 5 # 初始化连接池大小
min-idle: 10 # 最小维持的连接池大小
max-active: 50 # 最大可提供的连接数量
max-wait: 60000 # 最长等待时间
time-between-eviction-runs-millis: 6000 # 关闭空闲连接间隔(毫秒)
min-evictable-idle-time-millis: 30000 # 连接最小的生存时间
validation-query: SELECT 1 FROM dual # 数据库的状态检测
test-while-idle: true # 判断连接是否可用
test-on-borrow: false # 在获得连接之前是否要进行测试
test-on-return: false # 归还连接前是否需要进行测试
pool-prepared-statements: false # 不缓存PSTMT
max-pool-prepared-statement-per-connection-size: 20 # 配置PSTMT缓存个数
stat: # 监控配置
merge-sql: true # 统计相同的SQL命令
log-slow-sql: true # 记录慢SQL
slow-sql-millis: 2000 # 慢SQL执行时间标准
3.
package com.yix.config;
import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.logging.Slf4jLogFilter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.wall.WallFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
/**
* 自定义的Druid配置类
*
* @author wangdx
*/
@Configuration
public class DruidDataSourceConfiguration {
@Bean("yootkDruidDataSource") // 手工设置Bean名称
public DruidDataSource getYootkDruidDataSource(
@Value("${spring.yix.datasource.driver-class-name}")
String driverClassName, // 数据库驱动程序
@Value("${spring.yix.datasource.url}")
String url, // 数据库连接地址
@Value("${spring.yix.datasource.username}")
String username, // 数据库的用户名
@Value("${spring.yix.datasource.password}")
String password, // 数据库的用户名
@Value("${spring.yix.datasource.druid.initial-size}")
int initialSize, // 初始化连接数
@Value("${spring.yix.datasource.druid.min-idle}")
int minIdle, // 最小维持连接数
@Value("${spring.yix.datasource.druid.max-active}")
int maxActive, // 最大连接数
@Value("${spring.yix.datasource.druid.max-wait}")
long maxWait, // 最长等待时间
@Value("${spring.yix.datasource.druid.time-between-eviction-runs-millis}")
long timeBetweenEvictionRunsMillis, // 关闭空闲连接间隔
@Value("${spring.yix.datasource.druid.min-evictable-idle-time-millis}")
long minEvictableIdleTimeMillis, // 最小存活时间
@Value("${spring.yix.datasource.druid.validation-query}")
String validationQuery, // 验证查询
@Value("${spring.yix.datasource.druid.test-while-idle}")
boolean testWhileIdle, // 测试空闲连接是否可用
@Value("${spring.yix.datasource.druid.test-on-borrow}")
boolean testOnBorrow, // 测试后返回连接
@Value("${spring.yix.datasource.druid.test-on-return}")
boolean testOnReturn, // 测试后归还
@Value("${spring.yix.datasource.druid.pool-prepared-statements}")
boolean poolPreparedStatements, // 是否缓存PSTMT
@Value("${spring.yix.datasource.druid.max-pool-prepared-statement-per-connection-size}")
int maxPoolPreparedStatementPerConnectionSize, // PSTMT缓存个数
@Autowired StatFilter sqlStatFilter, // 注入SQL监控
@Autowired WallFilter sqlWallFilter, // 注入SQL防火墙
@Autowired Slf4jLogFilter logFilter // 日志记录
) {
DruidDataSource dataSource = new DruidDataSource(); // 实例化DataSource子类对象
dataSource.setDriverClassName(driverClassName); // 数据库驱动程序
dataSource.setUrl(url); // 数据库的连接地址
dataSource.setUsername(username); // 数据库用户名
dataSource.setPassword(password); // 数据库密码
dataSource.setInitialSize(initialSize); // 连接池初始化大小
dataSource.setMinIdle(minIdle); // 最小维持的连接数量
dataSource.setMaxActive(maxActive); // 最大的连接数量
dataSource.setMaxWait(maxWait); // 最大等待时间
dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); // 检查的间隔时间
dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); // 存活时间
dataSource.setValidationQuery(validationQuery); // 验证SQL
dataSource.setTestWhileIdle(testWhileIdle); // 测试连接是否可用
dataSource.setTestOnBorrow(testOnBorrow); // 获取时检测
dataSource.setTestOnReturn(testOnReturn); // 归还时检测
dataSource.setPoolPreparedStatements(poolPreparedStatements); // 是否缓存PSTMT
dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); // 缓存个数
// 定义所有可能存在的监控项集合
List<Filter> filterList = new ArrayList<>();
filterList.add(sqlStatFilter); // 配置监控项
filterList.add(sqlWallFilter); // SQL防火墙
filterList.add(logFilter); // SQL防火墙
dataSource.setProxyFilters(filterList); // 与DataSource整合
return dataSource;
}
}
4.
package com.yix.config;
import com.alibaba.druid.filter.logging.Slf4jLogFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author wangdx
*/
@Configuration
public class DruidLogConfig {
@Bean("logFilter")
public Slf4jLogFilter getLogFilter() {
Slf4jLogFilter logFilter = new Slf4jLogFilter();
logFilter.setDataSourceLogEnabled(true); // 启用数据库的日志
logFilter.setStatementExecutableSqlLogEnable(true); // 记录执行日志
return logFilter;
}
}
5.
package com.yix.config;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.support.jakarta.StatViewServlet;
import com.alibaba.druid.support.jakarta.WebStatFilter;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
import org.springframework.beans.factory.annotation.Value;
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 org.springframework.context.annotation.DependsOn;
/**
* @author wangdx
*/
@Configuration
public class DruidMonitorConfiguration {
@Bean("druidStatViewServlet")
public ServletRegistrationBean<StatViewServlet> getDruidStatViewServlet() {
ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>(
new StatViewServlet(), "/druid/*"); // 程序的访问路径
registrationBean.addInitParameter(StatViewServlet.PARAM_NAME_ALLOW, "127.0.0.1"); // 白名单
registrationBean.addInitParameter(StatViewServlet.PARAM_NAME_DENY, ""); // 黑名单
registrationBean.addInitParameter(StatViewServlet.PARAM_NAME_USERNAME, "muyan"); // 用户名
registrationBean.addInitParameter(StatViewServlet.PARAM_NAME_PASSWORD, "yootk");// 密码
registrationBean.addInitParameter(StatViewServlet.PARAM_NAME_RESET_ENABLE, "true"); // 允许重置
return registrationBean;
}
@Bean
@DependsOn("webStatFilter")
public FilterRegistrationBean<WebStatFilter> getDruidWebStatFilter(
WebStatFilter webStatFilter
) {
FilterRegistrationBean<WebStatFilter> registrationBean = new FilterRegistrationBean<>(webStatFilter);
registrationBean.addUrlPatterns("/*"); // 对所有的路径都进行监控配置
registrationBean.addInitParameter(WebStatFilter.PARAM_NAME_EXCLUSIONS,
"*.js,*.gif,*.jpg,*.bmp,*.css,*.ico,/druid/*"); // 路径排除
return registrationBean;
}
@Bean("webStatFilter")
public WebStatFilter getWebStatFilter() { // 获取WEB状态过滤
WebStatFilter statFilter = new WebStatFilter();
statFilter.setSessionStatEnable(true); // 对Session状态进行监控
return statFilter;
}
@Bean("sqlStatFilter")
public StatFilter getSQLStatFilter(
@Value("${spring.yix.datasource.druid.stat.merge-sql}")
boolean mergeSql,
@Value("${spring.yix.datasource.druid.stat.log-slow-sql}")
boolean logSlowSql,
@Value("${spring.yix.datasource.druid.stat.slow-sql-millis}")
long slowSqlMillis
) { // 定义关于SQL监控的处理部分
StatFilter filter = new StatFilter();
filter.setMergeSql(mergeSql); // 是否需要合并统计
filter.setLogSlowSql(logSlowSql); // 慢SQL记录
filter.setSlowSqlMillis(slowSqlMillis); // 慢SQL执行时间
return filter;
}
@Bean("sqlWallConfig")
public WallConfig getSQLWallConfig() { // 获取防火墙
WallConfig wc = new WallConfig(); // 配置防火墙
wc.setMultiStatementAllow(true); // 允许进行多个Statatement操作(批处理)
wc.setDeleteAllow(false); // 不允许执行删除
return wc;
}
@Bean("sqlWallFilter")
public WallFilter getSQLWallFilter(WallConfig wallConfig) { // 注入防火墙配置项
WallFilter filter = new WallFilter();
filter.setConfig(wallConfig);
return filter;
}
}
6.
package com.yix.config;
import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
/**
* Spring监控配置类
*
* @author wangdx
*/
@Configuration
public class DruidSpringConfig {
@Bean("druidStatInterceptor")
public DruidStatInterceptor getDruidStatInterceptor() {
DruidStatInterceptor interceptor = new DruidStatInterceptor(); // 创建Druid拦截器
return interceptor;
}
@Bean("druidSpringStatPointcut")
@Scope("prototype")
public JdkRegexpMethodPointcut getDruidSpringStatPointcut() { // 获取切面
JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
pointcut.setPatterns("com.yix.service.*", "com.yix.action.*", "com.yix.dao.*");
return pointcut;
}
@Bean("druidSpringStatAdvisor")
public DefaultPointcutAdvisor getDruidSpringStatAdvisor(
DruidStatInterceptor druidStatInterceptor,
JdkRegexpMethodPointcut jdkRegexpMethodPointcut
) {
DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
defaultPointcutAdvisor.setPointcut(jdkRegexpMethodPointcut);
defaultPointcutAdvisor.setAdvice(druidStatInterceptor);
return defaultPointcutAdvisor;
}
}
7.
package com.yix.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
/**
* @author wangdx
*/
@Configuration
public class SpringJdbcConfiguration {
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
JdbcTemplate template = new JdbcTemplate();
template.setDataSource(dataSource);
return template;
}
}
4.
@ExtendWith(SpringExtension.class) // 使用JUnit5测试工具
@WebAppConfiguration // 启动WEB运行环境
@SpringBootTest(classes = DruidApplication.class) // 配置程序启动类
public class TestDruidDataSource {
@Autowired
private DataSource dataSource;
@Test
public void testDruid() { // 进行响应测试
try {
System.out.println(this.dataSource.getConnection());
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
单数据源-druid-yml
1.
api(libraries.'druid-spring-boot-starter')
2.
server:
port: 80
spring:
datasource: # 数据源配置
druid: # druid相关配置
type: com.alibaba.druid.pool.DruidDataSource # 配置数据源的类型
driver-class-name: com.mysql.cj.jdbc.Driver # 配置MySQL的驱动程序类
url: jdbc:mysql://192.168.16.8:3306/yootk # 数据库连接地址
username: root # 数据库用户名
password: root # 数据库连接密码
initial-size: 5 # 初始化连接池大小
min-idle: 10 # 最小维持的连接池大小
max-active: 20 # 最大支持的连接池大小
max-wait: 60000 # 最大等待时间(毫秒)
connectTimeout: 30000 #配置连接超时时间
socketTimeout: 60000 # 配置网络超时时间
time-between-eviction-runs-millis: 60000 # 关闭空闲连接间隔(毫秒)
min-evictable-idle-time-millis: 300000 # 连接最小生存时间(毫秒)
maxEvictableIdleTimeMillis: 900000 #配置一个连接在池中最大生存的时间,单位是毫秒
validation-query: SELECT 1 FROM dual # 数据库状态检测
test-while-idle: true # 申请连接的时候检测连接是否有效
test-on-borrow: false # 申请连接时检测连接是否有效
test-on-return: false # 归还连接时检测连接是否有效
pool-prepared-statements: false # PSCache缓存
max-pool-prepared-statement-per-connection-size: 20 # 配置PS缓存
filters: stat, wall, slf4j # 开启过滤
stat-view-servlet: # 监控界面配置
enabled: true # 启用druid监控界面
allow: 127.0.0.1 # 设置访问白名单
login-username: yix # 用户名
login-password: yix # 密码
reset-enable: true # 允许重置
url-pattern: /druid/* # 访问路径
web-stat-filter: # WEB监控
enabled: true # 启动URI监控
url-pattern: /* # 跟踪根路径下的全部服务
exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*" # 跟踪排除
filter: # Druid过滤器
slf4j: # 日志
enabled: true # 启用SLF4j监控
data-source-log-enabled: true # 启用数据库日志
statement-executable-sql-log-enable: true # 执行日志
result-set-log-enabled: true # ResultSet日志启用
stat: # SQL监控
merge-sql: true # 统计时合并相同的SQL命令
log-slow-sql: true # 当SQL执行缓慢时是否要进行记录
slow-sql-millis: 1 # 设置慢SQL的执行时间标准,单位:毫秒
wall: # SQL防火墙
enabled: true # 启用SQL防火墙
config: # 配置防火墙规则
multi-statement-allow: true # 允许执行批量SQL
delete-allow: false # 禁止执行删除语句
aop-patterns: "com.yix.web.action.*" # Spring监控
多数据源-druid