mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-11-03 13:55:32 +08:00
update 优化 sql输出拦截器 支持根据表名忽略sql
This commit is contained in:
parent
dce62a9d5d
commit
42e7196b13
@ -82,6 +82,8 @@ mybatis-plus:
|
||||
enabled: true
|
||||
# 输出方式,可选 console、log
|
||||
output: console
|
||||
# 忽略高频轮询表的成功 SQL 日志;执行异常仍会输出
|
||||
ignore-tables: [flow_event_wait]
|
||||
|
||||
--- # 数据源配置
|
||||
spring:
|
||||
|
||||
@ -85,6 +85,8 @@ mybatis-plus:
|
||||
enabled: false
|
||||
# 输出方式,可选 console、log
|
||||
output: console
|
||||
# 忽略高频轮询表的成功 SQL 日志;执行异常仍会输出
|
||||
ignore-tables: [ flow_event_wait ]
|
||||
|
||||
--- # 数据源配置
|
||||
spring:
|
||||
|
||||
@ -3,6 +3,9 @@ package org.dromara.common.mybatis.config.properties;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* SQL 日志配置。
|
||||
*
|
||||
@ -22,4 +25,9 @@ public class SqlLogProperties {
|
||||
*/
|
||||
private String output = "console";
|
||||
|
||||
/**
|
||||
* 不输出成功执行日志的表名;执行异常仍会输出。
|
||||
*/
|
||||
private List<String> ignoreTables = new ArrayList<>();
|
||||
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 完整 SQL 日志拦截器。
|
||||
@ -55,6 +56,8 @@ public class SqlLogInterceptor implements Interceptor {
|
||||
*/
|
||||
private static final String BLANK_REGEX = "\\s+";
|
||||
|
||||
private static final Pattern SQL_STRING_LITERAL = Pattern.compile("'(?:''|[^'])*'");
|
||||
|
||||
/**
|
||||
* 日期时间格式。
|
||||
*/
|
||||
@ -75,8 +78,17 @@ public class SqlLogInterceptor implements Interceptor {
|
||||
*/
|
||||
private final SqlLogProperties sqlLogProperties;
|
||||
|
||||
private final List<Pattern> ignoredTablePatterns;
|
||||
|
||||
public SqlLogInterceptor(SqlLogProperties sqlLogProperties) {
|
||||
this.sqlLogProperties = sqlLogProperties;
|
||||
this.ignoredTablePatterns = sqlLogProperties.getIgnoreTables().stream()
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.map(String::trim)
|
||||
.map(table -> Pattern.compile("(?i)\\b(?:FROM|JOIN|UPDATE|INTO)\\s+"
|
||||
+ "(?:[`\"\\[]?[A-Za-z_][A-Za-z0-9_]*[`\"\\]]?\\s*\\.\\s*)?"
|
||||
+ "[`\"\\[]?" + Pattern.quote(table) + "[`\"\\]]?(?=\\s|[,);]|$)"))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -104,11 +116,27 @@ public class SqlLogInterceptor implements Interceptor {
|
||||
* @param throwable 执行异常
|
||||
*/
|
||||
private void printSql(MappedStatement mappedStatement, BoundSql boundSql, long elapsedTime, Throwable throwable) {
|
||||
if (throwable == null && isIgnoredTableSql(boundSql.getSql())) {
|
||||
return;
|
||||
}
|
||||
String fullSql = buildFullSql(mappedStatement.getConfiguration(), boundSql);
|
||||
String message = buildLogMessage(mappedStatement, elapsedTime, fullSql, throwable);
|
||||
printChunk(message);
|
||||
}
|
||||
|
||||
boolean isIgnoredTableSql(String sql) {
|
||||
if (ignoredTablePatterns.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
String statement = sql.indexOf('\'') >= 0 ? SQL_STRING_LITERAL.matcher(sql).replaceAll("''") : sql;
|
||||
for (Pattern pattern : ignoredTablePatterns) {
|
||||
if (pattern.matcher(statement).find()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建日志内容。
|
||||
*
|
||||
|
||||
@ -0,0 +1,84 @@
|
||||
package org.dromara.common.mybatis.interceptor;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
||||
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
|
||||
import org.apache.ibatis.mapping.Environment;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
|
||||
import org.dromara.common.mybatis.config.properties.SqlLogProperties;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class SqlLogInterceptorTest {
|
||||
|
||||
@Test
|
||||
void ignoredTableStillExecutesAndOtherTableStillLogs() throws Exception {
|
||||
SqlLogProperties properties = new SqlLogProperties();
|
||||
properties.setIgnoreTables(List.of("flow_event_wait"));
|
||||
SqlLogInterceptor interceptor = new SqlLogInterceptor(properties);
|
||||
String url = "jdbc:h2:mem:sql_log_" + UUID.randomUUID().toString().replace("-", "") + ";DB_CLOSE_DELAY=-1";
|
||||
UnpooledDataSource dataSource = new UnpooledDataSource("org.h2.Driver", url, "sa", "");
|
||||
try (Connection connection = dataSource.getConnection(); Statement statement = connection.createStatement()) {
|
||||
statement.execute("CREATE TABLE flow_event_wait (id BIGINT PRIMARY KEY)");
|
||||
statement.execute("CREATE TABLE audit_record (id BIGINT PRIMARY KEY)");
|
||||
statement.execute("INSERT INTO flow_event_wait VALUES (1)");
|
||||
statement.execute("INSERT INTO audit_record VALUES (2)");
|
||||
}
|
||||
|
||||
MybatisConfiguration configuration = new MybatisConfiguration();
|
||||
configuration.setEnvironment(new Environment("h2", new JdbcTransactionFactory(), dataSource));
|
||||
configuration.addInterceptor(interceptor);
|
||||
configuration.addMapper(LogMapper.class);
|
||||
SqlSessionFactory factory = new MybatisSqlSessionFactoryBuilder().build(configuration);
|
||||
PrintStream originalErr = System.err;
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
try (PrintStream capture = new PrintStream(output, true, StandardCharsets.UTF_8)) {
|
||||
System.setErr(capture);
|
||||
try (SqlSession session = factory.openSession()) {
|
||||
assertEquals(1L, session.getMapper(LogMapper.class).eventWaitId());
|
||||
assertEquals(2L, session.getMapper(LogMapper.class).auditId());
|
||||
}
|
||||
} finally {
|
||||
System.setErr(originalErr);
|
||||
}
|
||||
String logs = output.toString(StandardCharsets.UTF_8);
|
||||
assertFalse(logs.contains("flow_event_wait"));
|
||||
assertTrue(logs.contains("audit_record"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesTableReferencesWithoutMatchingLiteralsOrSimilarNames() {
|
||||
SqlLogProperties properties = new SqlLogProperties();
|
||||
properties.setIgnoreTables(List.of("flow_event_wait"));
|
||||
SqlLogInterceptor interceptor = new SqlLogInterceptor(properties);
|
||||
|
||||
assertTrue(interceptor.isIgnoredTableSql("select * from flow_event_wait where id = ?"));
|
||||
assertTrue(interceptor.isIgnoredTableSql("select * from `app`.`flow_event_wait`"));
|
||||
assertTrue(interceptor.isIgnoredTableSql("select * from audit_record join FLOW_EVENT_WAIT w on w.id = audit_record.id"));
|
||||
assertTrue(interceptor.isIgnoredTableSql("update flow_event_wait set status = ?"));
|
||||
assertFalse(interceptor.isIgnoredTableSql("select 'from flow_event_wait' from audit_record"));
|
||||
assertFalse(interceptor.isIgnoredTableSql("select * from flow_event_wait_history"));
|
||||
}
|
||||
|
||||
interface LogMapper {
|
||||
@Select("SELECT id FROM flow_event_wait")
|
||||
Long eventWaitId();
|
||||
|
||||
@Select("SELECT id FROM audit_record")
|
||||
Long auditId();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user