初始化仓库

This commit is contained in:
2026-04-21 15:08:07 +08:00
parent 444d984122
commit b5119afb9f
195 changed files with 11034 additions and 19 deletions

20
xtools-boot-db/pom.xml Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot</artifactId>
<version>5.0.0</version>
</parent>
<packaging>pom</packaging>
<artifactId>xtools-boot-db</artifactId>
<!-- 子模块 -->
<modules>
<module>xtools-boot-db-mybatis</module>
<module>xtools-boot-db-mybatis-plus</module>
</modules>
</project>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-db</artifactId>
<version>5.0.0</version>
</parent>
<artifactId>xtools-boot-db-mybatis-plus</artifactId>
<!-- 依赖 -->
<dependencies>
<!-- xtools-boot begin -->
<!-- xtools-boot-core -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-core</artifactId>
</dependency>
<!-- xtools-boot end -->
<!-- SpringBoot begin -->
<!-- mybatis-plus begin -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot4-starter</artifactId>
</dependency>
<!-- mybatis-plus end -->
<!-- SpringBoot end -->
</dependencies>
</project>

View File

@@ -0,0 +1,28 @@
package xtools.boot.db.mybatisplus;
import org.springframework.context.annotation.Import;
import xtools.boot.core.utils.ModuleLoadUtils;
import xtools.boot.db.mybatisplus.selector.BootDbMybatisPlusImportSelector;
/**
* <p>Title : BootCacheRedisConfiguration</p>
* <p>Description : BootCacheRedisConfiguration</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/01/01 09:30
*/
@Import(BootDbMybatisPlusImportSelector.class)
public class BootDbMybatisPlusConfiguration {
/**
* 构造方法
*/
public BootDbMybatisPlusConfiguration() {
ModuleLoadUtils.loadSuccess(BootDbMybatisPlusConfiguration.class);
}
}

View File

@@ -0,0 +1,35 @@
package xtools.boot.db.mybatisplus.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* <p>Title : MybatisPlusConfig</p>
* <p>Description : MybatisPlusConfig</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/1/5 10:15
*/
@Configuration
public class MybatisPlusConfig {
/**
* 配置 MybatisPlus 拦截器
*
* @return MybatisPlus 拦截器
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

View File

@@ -0,0 +1,36 @@
package xtools.boot.db.mybatisplus.selector;
import org.jspecify.annotations.NonNull;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* <p>Title : BootDbMybatisPlusImportSelector</p>
* <p>Description : BootDbMybatisPlusImportSelector</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/01/01 09:30
*/
public class BootDbMybatisPlusImportSelector implements ImportBeanDefinitionRegistrar {
/**
* 根据给定的注释元数据,根据需要注册bean
*
* @param importingClassMetadata AnnotationMetadata
* @param registry BeanDefinitionRegistry
*/
@Override
public void registerBeanDefinitions(@NonNull AnnotationMetadata importingClassMetadata, @NonNull BeanDefinitionRegistry registry) {
// 构建扫描对象
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, true);
// 扫描包下路径
scanner.scan("xtools.boot.db.mybatisplus");
}
}

View File

@@ -0,0 +1,59 @@
package xtools.boot.db.mybatisplus.utils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import xtools.base.config.BaseParams;
import xtools.core.ArrUtils;
import java.time.Instant;
import java.util.Objects;
/**
* <p>Title : QueryUtils</p>
* <p>Description : QueryUtils</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/1/17 19:16
*/
public class QueryUtils implements BaseParams {
/**
* 添加时间范围查询
*
* @param query 查询条件
* @param timeRange 时间范围
* @param timeField 时间字段
* @param <T> 泛型
*/
public static <T> void addTimeRange(LambdaQueryWrapper<T> query, Instant[] timeRange, SFunction<T, ?> timeField) {
if (ArrUtils.isEmpty(timeRange) || timeRange.length != CP_NUM2) {
return;
}
query.ge(Objects.nonNull(timeRange[CP_NUM0]), timeField, timeRange[CP_NUM0]);
query.le(Objects.nonNull(timeRange[CP_NUM1]), timeField, timeRange[CP_NUM1]);
}
/**
* 获取分页条件
*
* @param currentPage 当前页
* @param pageSize 页面大小
* @param <T> 泛型
* @return 分页条件
*/
public static <T> Page<T> getPage(Integer currentPage, Integer pageSize) {
if (Objects.isNull(currentPage) || currentPage < CP_NUM1) {
currentPage = CP_NUM1;
}
if (Objects.isNull(pageSize) || pageSize < CP_NUM1) {
pageSize = CP_NUM10;
}
return new Page<>(currentPage, pageSize);
}
}

View File

@@ -0,0 +1 @@
xtools.boot.db.mybatisplus.BootDbMybatisPlusConfiguration

View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-db</artifactId>
<version>5.0.0</version>
</parent>
<artifactId>xtools-boot-db-mybatis</artifactId>
<!-- 依赖 -->
<dependencies>
<!-- xtools-boot begin -->
<!-- xtools-boot-core -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-core</artifactId>
</dependency>
<!-- xtools-boot-log -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-log</artifactId>
</dependency>
<!-- xtools-boot-thread -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-thread</artifactId>
</dependency>
<!-- xtools-boot end -->
<!-- SpringBoot begin -->
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- SpringBoot end -->
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- Druid(数据库连接池) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-4-starter</artifactId>
</dependency>
<!-- fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
</dependency>
<!-- servlet-api -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,30 @@
package xtools.boot.db.mybatis;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Import;
import xtools.boot.core.utils.ModuleLoadUtils;
import xtools.boot.db.mybatis.selector.BootDbMybatisImportSelector;
/**
* <p>Title : BootDbMybatisConfiguration</p>
* <p>Description : BootDbMybatisConfiguration</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/01/01 09:30
*/
@MapperScan({"xtools.boot.db.mybatis.mapper"})
@Import(BootDbMybatisImportSelector.class)
public class BootDbMybatisConfiguration {
/**
* 构造方法
*/
public BootDbMybatisConfiguration() {
ModuleLoadUtils.loadSuccess(BootDbMybatisConfiguration.class);
}
}

View File

@@ -0,0 +1,32 @@
package xtools.boot.db.mybatis.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* <p>Title : MyBatisConfig</p>
* <p>Description : MyBatisConfig</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/2/11 14:46
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "mybatis")
public class MyBatisConfig {
/**
* 是否开启MyBatis监控
*/
private Boolean monitor = true;
/**
* 慢查询时间阈值
*/
private Integer slowTime = 3000;
}

View File

@@ -0,0 +1,96 @@
package xtools.boot.db.mybatis.druid;
import com.alibaba.druid.spring.boot4.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import xtools.core.StringUtils;
import java.io.IOException;
/**
* <p>Title : DruidConf</p>
* <p>Description : DruidConf</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2025年8月13日 上午8:06:06
*/
@Component
@Configuration
public class DruidConf {
/**
* 广告过滤
*
* @param properties Druid配置信息
* @return 广告过滤
*/
@Bean
@ConditionalOnProperty(name = "spring.datasource.druid.web-stat-filter.enabled", havingValue = "true")
public FilterRegistrationBean<Filter> removeDruidFilterRegistrationBean(DruidStatProperties properties) {
DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
String urlPattern = config.getUrlPattern();
// 提取common.js的配置路径
String pattern = StringUtils.isEmpty(urlPattern) ? "/druid/**" : urlPattern;
String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
final String filePath = "support/http/resources/js/common.js";
// 创建filter进行过滤
Filter filter = new Filter() {
/**
* 初始化
*
* @param filterConfig FilterConfig
*/
@Override
public void init(FilterConfig filterConfig) {
}
/**
* 过滤器
*
* @param request ServletRequest
* @param response ServletResponse
* @param chain FilterChain
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
// 重置缓冲区,响应头不会被重置
response.resetBuffer();
// 获取common.js
String text = Utils.readFromResource(filePath);
// 正则替换banner, 除去底部的广告信息
text = text.replaceAll("<a.*?banner\"></a><br/>", "");
text = text.replaceAll("powered.*?shrek.wang</a>", "");
response.getWriter().write(text);
}
/**
* 销毁
*/
@Override
public void destroy() {
}
};
FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(filter);
registrationBean.addUrlPatterns(commonJsPattern);
return registrationBean;
}
}

View File

@@ -0,0 +1,33 @@
package xtools.boot.db.mybatis.druid;
import org.springframework.stereotype.Component;
import xtools.boot.core.interfaces.FilterWhitelist;
import java.util.Set;
/**
* <p>Title : DruidFilterWhitelist</p>
* <p>Description : DruidFilterWhitelist</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/3/8 12:28
*/
@Component
public class DruidFilterWhitelist implements FilterWhitelist {
/**
* 添加过滤器白名单
*
* @return 过滤器白名单
*/
@Override
public Set<String> add() {
return Set.of(
"/druid/**"
);
}
}

View File

@@ -0,0 +1,121 @@
package xtools.boot.db.mybatis.enums;
import xtools.boot.api.enums.BaseEnum;
/**
* <p>Title : MySqlMonitorEnums</p>
* <p>Description : MySqlMonitorEnums</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/2/3 10:31
*/
public enum MySqlMonitorEnums implements BaseEnum {
// 进程列表
PROCESSLIST(1, "进程列表", "SHOW FULL PROCESSLIST"),
// 变量
VARIABLES(2, "变量", "SHOW GLOBAL VARIABLES"),
// 状态
STATUS(3, "状态", "SHOW STATUS"),
// 需要权限
// // 查看正在进行中的事务
// INNODB_TRX(100, "查看正在进行中的事务", "SELECT * FROM information_schema.INNODB_TRX"),
// // 查看正在锁的事务
// INNODB_LOCKS(101, "查看正在锁的事务", "SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS"),
// // 查看等待锁的事务
// INNODB_LOCK_WAITS(102, "查看等待锁的事务", "SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS"),
// // 查询是否锁表
// LOCK_TABLES(103, "查询是否锁表", "SHOW OPEN TABLES where In_use > 0"),
// // 查看最近死锁的日志
// INNODB_STATUS(104, "查看最近死锁的日志", "show engine innodb status"),
;
/**
* 编码
*/
private final int code;
/**
* 说明
*/
private final String desc;
/**
* SQL语句
*/
private final String sql;
/**
* 初始化方法
*
* @param code Code
* @param desc 说明
* @param sql SQL
*/
MySqlMonitorEnums(int code, String desc, String sql) {
this.code = code;
this.desc = desc;
this.sql = sql;
}
/**
* 判断枚举值类型
*
* @param code 枚举值
* @return 枚举值类型
*/
public static MySqlMonitorEnums valueOf(int code) {
for (MySqlMonitorEnums type : values()) {
if (type.code == code) {
return type;
}
}
throw new IllegalArgumentException("unknown code, code=" + code);
}
/**
* 获取所有枚举
*
* @return 所有枚举
*/
@Override
public BaseEnum[] all() {
return values();
}
/**
* 获取枚举编码
*
* @return 枚举编码
*/
@Override
public int code() {
return code;
}
/**
* 获取枚举说明
*
* @return 枚举说明
*/
@Override
public String desc() {
return desc;
}
/**
* 获取SQL
*
* @return SQL
*/
public String getSql() {
return sql;
}
}

View File

@@ -0,0 +1,235 @@
package xtools.boot.db.mybatis.interceptor;
import com.alibaba.druid.pool.DruidPooledPreparedStatement;
import com.alibaba.druid.proxy.jdbc.JdbcParameter;
import com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import jakarta.annotation.Resource;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.jspecify.annotations.NonNull;
import org.springframework.stereotype.Component;
import xtools.boot.api.model.dto.log.LogTrack;
import xtools.boot.db.mybatis.config.MyBatisConfig;
import xtools.boot.log.LogBus;
import xtools.boot.log.enums.LogBusBaseType;
import xtools.boot.log.holder.LogTrackHolder;
import xtools.boot.thread.utils.VirtualThreadTaskUtils;
import xtools.core.CollectionUtils;
import xtools.core.enums.LogLevel;
import xtools.core.enums.TimePattern;
import xtools.core.time.InstantUtils;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.Map;
import java.util.Objects;
/**
* <p>Title : MyBatisInterceptor</p>
* <p>Description : MyBatisInterceptor</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/2/11 14:35
*/
@Component
@Intercepts({
@Signature(type = StatementHandler.class, method = MyBatisInterceptor.QUERY, args = {Statement.class, ResultHandler.class}),
@Signature(type = StatementHandler.class, method = MyBatisInterceptor.UPDATE, args = {Statement.class})
})
public class MyBatisInterceptor implements Interceptor {
/**
* 查询方法名
**/
public final static String QUERY = "query";
/**
* 更新方法名
**/
public final static String UPDATE = "update";
@Resource
private MyBatisConfig conf;
/**
* 拦截操作
*
* @param invocation 调用参数
* @return 结果
*/
@Override
public Object intercept(@NonNull Invocation invocation) throws Throwable {
LogTrack log = LogTrackHolder.getDefNull();
// 是否启动监控
if (!conf.getMonitor() || Objects.isNull(log) || !log.save()) {
return invocation.proceed();
}
// 执行结果
Object result = null;
// 异常信息
Exception err = null;
// 开始时间
long startTime = System.currentTimeMillis();
try {
result = invocation.proceed();
return result;
} catch (Exception e) {
err = e;
throw e;
} finally {
// 获取当前线程日志信息
LogTrack logTrack = LogTrackHolder.get();
// 结束时间
long endTime = System.currentTimeMillis();
// 执行时间
long execTime = endTime - startTime;
// 执行结果信息
final Object execResult = result;
// 转换参数
Throwable ft = err;
// 处理SQL日志
VirtualThreadTaskUtils.simple(() -> {
// 获取运行参数
Object runArg = invocation.getArgs()[0];
// 读写标识
String rw = QUERY.equals(invocation.getMethod().getName()) ? "" : "";
// 日志信息
JSONObject logData = JSONObject.of(
"startTime", InstantUtils.format(InstantUtils.from(startTime), TimePattern.ALL),
"execTime", execTime,
"result", execResult,
"rw", rw
);
// 是否为慢SQL
logData.put("slowSql", execTime >= conf.getSlowTime());
// 日志分析
this.analysisLog(logTrack, logData, runArg, ft);
});
}
}
/**
* 日志分析
*
* @param logTrack 日志信息
* @param log 日志信息
* @param runArg 运行参数
* @param t 异常
*/
private void analysisLog(LogTrack logTrack, JSONObject log, Object runArg, Throwable t) {
try {
// 获取sql信息
JSONObject sqlInfo = this.getSqlInfo(runArg, logTrack, log);
if (CollectionUtils.isNotEmpty(sqlInfo)) {
log.putAll(sqlInfo);
}
} catch (Exception e) {
t = e;
} finally {
this.execLog(logTrack, log, t);
}
}
/**
* 获取SQL信息
*
* @param runArg 运行参数
* @param log 日志信息
* @return SQL信息
*/
private JSONObject getSqlInfo(Object runArg, LogTrack logTrack, JSONObject log) {
// 执行SQL
String sql;
// 参数
JSONArray params = new JSONArray();
// 个性化参数获取方式
if (DruidPooledPreparedStatement.class.equals(runArg.getClass())) {
// 开启druid监控获取参数方式
DruidPooledPreparedStatement statement = (DruidPooledPreparedStatement) runArg;
sql = statement.getSql();
try {
JSONArray dp = this.getParams(statement);
if (dp != null) {
params = dp;
}
} catch (Exception e) {
this.execLog(logTrack, log, e);
}
} else {
sql = runArg.toString();
// 获取完整SQL
sql = sql.substring(sql.indexOf(":") + 1);
}
// 格式化Sql
sql = sql.replaceAll(",", ", ").replaceAll("\t+", " ").replaceAll("\n+", " ").replaceAll(" +", " ").trim();
// 结果封装
return JSONObject.of("sql", sql, "params", params);
}
/**
* 获取参数
*
* @param statement DruidPooledPreparedStatement
* @return 参数集合
*/
private JSONArray getParams(DruidPooledPreparedStatement statement) {
if (statement == null) {
return null;
}
PreparedStatement ps = statement.getRawStatement();
if (ps == null) {
return null;
}
if (!PreparedStatementProxyImpl.class.equals(ps.getClass())) {
return null;
}
PreparedStatementProxyImpl psp = (PreparedStatementProxyImpl) ps;
int parametersSize = psp.getParametersSize();
if (parametersSize <= 0) {
return null;
}
Map<Integer, JdbcParameter> paramMap = psp.getParameters();
if (CollectionUtils.isEmpty(paramMap)) {
return null;
}
// 参数
JSONArray params = new JSONArray();
paramMap.forEach((key, value) -> params.add(value.getValue()));
return params;
}
/**
* 处理SQL日志
*
* @param logTrack 日志信息
* @param log 日志信息
* @param t 异常
*/
private void execLog(LogTrack logTrack, JSONObject log, Throwable t) {
// 是否为慢SQL
boolean slowSql = log.getBooleanValue("slowSql", false);
// 日志级别
LogLevel level = LogLevel.INFO;
if (t != null) {
level = LogLevel.ERROR;
} else if (slowSql) {
level = LogLevel.WARN;
}
// 获取读写
String rw = log.getString("rw");
log.remove("rw");
LogBus.init(level, LogBusBaseType.MYBATIS, logTrack).title("SQL/" + rw).data(log).error(t).save();
}
}

View File

@@ -0,0 +1,37 @@
package xtools.boot.db.mybatis.mapper;
import com.alibaba.fastjson2.JSONObject;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* <p>Title : MonitorDatabasesMapper</p>
* <p>Description : MonitorDatabasesMapper</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/2/14 11:49
*/
@Mapper
public interface MonitorDatabasesMapper {
/**
* 监控MySQL
*
* @param sql SQL语句
* @return 监控数据
*/
@Select({
"<script>",
"${sql}",
"</script>"
})
List<JSONObject> mysql(@Param("sql") String sql);
}

View File

@@ -0,0 +1,43 @@
package xtools.boot.db.mybatis.monitor;
import com.alibaba.fastjson2.JSONObject;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import xtools.boot.api.exection.BizError;
import xtools.boot.db.mybatis.enums.MySqlMonitorEnums;
import xtools.boot.db.mybatis.mapper.MonitorDatabasesMapper;
import java.util.List;
import java.util.Objects;
/**
* <p>Title : MySqlMonitor</p>
* <p>Description : MySqlMonitor</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/2/14 16:18
*/
@Component
@RequiredArgsConstructor
public class MySqlMonitor {
private final MonitorDatabasesMapper monitorDatabasesMapper;
/**
* 获取MySQL监控信息
*
* @param type 枚举
* @return MySQL监控信息
*/
public List<JSONObject> info(MySqlMonitorEnums type) {
if (Objects.isNull(type)) {
throw new BizError("类型参数不能为空");
}
return monitorDatabasesMapper.mysql(type.getSql());
}
}

View File

@@ -0,0 +1,36 @@
package xtools.boot.db.mybatis.selector;
import org.jspecify.annotations.NonNull;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* <p>Title : BootDbMybatisImportSelector</p>
* <p>Description : BootDbMybatisImportSelector</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/01/01 09:30
*/
public class BootDbMybatisImportSelector implements ImportBeanDefinitionRegistrar {
/**
* 根据给定的注释元数据,根据需要注册bean
*
* @param importingClassMetadata AnnotationMetadata
* @param registry BeanDefinitionRegistry
*/
@Override
public void registerBeanDefinitions(@NonNull AnnotationMetadata importingClassMetadata, @NonNull BeanDefinitionRegistry registry) {
// 构建扫描对象
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, true);
// 扫描包下路径
scanner.scan("xtools.boot.db.mybatis");
}
}