Skip to content

Commit

Permalink
✨ 调整 sql 日志打印
Browse files Browse the repository at this point in the history
  • Loading branch information
ChunMengLu committed Jan 2, 2025
1 parent 0e697aa commit 8c3a3ca
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 189 deletions.
4 changes: 4 additions & 0 deletions blade-starter-mybatis/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
<groupId>org.mybatis</groupId>
<artifactId>mybatis-typehandlers-jsr310</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
</dependency>
<!--Blade-->
<dependency>
<groupId>org.springblade</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springblade.core.mp.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.ArrayList;
import java.util.List;

/**
* druid 连接池配置
*
* @author L.cm
*/
@Getter
@Setter
@ConfigurationProperties("blade.mybatis-plus")
public class BladeMybatisPlusProperties {

/**
* 是否打印 sql
*/
private boolean sqlLog = true;

/**
* sql 打印正则过滤
*/
private List<String> sqlLogPatterns = new ArrayList<>();

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
import net.sf.jsqlparser.expression.StringValue;
import org.mybatis.spring.annotation.MapperScan;
import org.springblade.core.mp.intercept.QueryInterceptor;
import org.springblade.core.mp.logger.SqlLogFilter;
import org.springblade.core.mp.plugins.BladePaginationInterceptor;
import org.springblade.core.mp.plugins.SqlLogInterceptor;
import org.springblade.core.mp.props.MybatisPlusProperties;
import org.springblade.core.secure.utils.SecureUtil;
import org.springblade.core.tool.constant.BladeConstant;
Expand All @@ -46,7 +46,10 @@
@AutoConfiguration
@AllArgsConstructor
@MapperScan("org.springblade.**.mapper.**")
@EnableConfigurationProperties(MybatisPlusProperties.class)
@EnableConfigurationProperties({
MybatisPlusProperties.class,
BladeMybatisPlusProperties.class
})
public class MybatisPlusConfiguration {


Expand Down Expand Up @@ -101,8 +104,8 @@ public MybatisPlusInterceptor mybatisPlusInterceptor(ObjectProvider<QueryInterce
*/
@Bean
@ConditionalOnProperty(value = "blade.mybatis-plus.sql-log", matchIfMissing = true)
public SqlLogInterceptor sqlLogInterceptor() {
return new SqlLogInterceptor();
public SqlLogFilter sqlLogFilter(BladeMybatisPlusProperties properties) {
return new SqlLogFilter(properties);
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springblade.core.mp.logger;

import com.alibaba.druid.DbType;
import com.alibaba.druid.filter.FilterChain;
import com.alibaba.druid.filter.FilterEventAdapter;
import com.alibaba.druid.proxy.jdbc.JdbcParameter;
import com.alibaba.druid.proxy.jdbc.ResultSetProxy;
import com.alibaba.druid.proxy.jdbc.StatementProxy;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.mp.config.BladeMybatisPlusProperties;
import org.springblade.core.tool.utils.StringUtil;

import java.sql.SQLException;
import java.time.temporal.TemporalAccessor;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
* 打印可执行的 sql 日志
*
* <p>
* 参考:<a href="https://jfinal.com/share/2204">https://jfinal.com/share/2204</a>
* </p>
*
* @author L.cm
*/
@Slf4j
public class SqlLogFilter extends FilterEventAdapter {
private static final SQLUtils.FormatOption FORMAT_OPTION = new SQLUtils.FormatOption(false, false);
private final BladeMybatisPlusProperties properties;
private final List<Pattern> sqlLogPatternList;

public SqlLogFilter(BladeMybatisPlusProperties properties) {
this.properties = properties;
this.sqlLogPatternList = properties.getSqlLogPatterns().stream().map(Pattern::compile).toList();
}

@Override
protected void statementExecuteBefore(StatementProxy statement, String sql) {
statement.setLastExecuteStartNano();
}

@Override
protected void statementExecuteBatchBefore(StatementProxy statement) {
statement.setLastExecuteStartNano();
}

@Override
protected void statementExecuteUpdateBefore(StatementProxy statement, String sql) {
statement.setLastExecuteStartNano();
}

@Override
protected void statementExecuteQueryBefore(StatementProxy statement, String sql) {
statement.setLastExecuteStartNano();
}

@Override
protected void statementExecuteAfter(StatementProxy statement, String sql, boolean firstResult) {
statement.setLastExecuteTimeNano();
}

@Override
protected void statementExecuteBatchAfter(StatementProxy statement, int[] result) {
statement.setLastExecuteTimeNano();
}

@Override
protected void statementExecuteQueryAfter(StatementProxy statement, String sql, ResultSetProxy resultSet) {
statement.setLastExecuteTimeNano();
}

@Override
protected void statementExecuteUpdateAfter(StatementProxy statement, String sql, int updateCount) {
statement.setLastExecuteTimeNano();
}

@Override
public void statement_close(FilterChain chain, StatementProxy statement) throws SQLException {
// 先调用父类关闭 statement
super.statement_close(chain, statement);
// 支持动态关闭
if (!properties.isSqlLog()) {
return;
}
// 是否开启调试
if (!log.isInfoEnabled()) {
return;
}
// 打印可执行的 sql
String sql = statement.getBatchSql();
// sql 为空直接返回
if (StringUtils.isEmpty(sql)) {
return;
}
boolean isSqlMatch = sqlLogPatternList.stream()
.anyMatch(pattern -> pattern.matcher(sql).matches());
if (!isSqlMatch) {
log.debug("sql:{} not match in SqlPatternList:{}", sql, properties.getSqlLogPatterns());
return;
}
int parametersSize = statement.getParametersSize();
List<Object> parameters = new ArrayList<>(parametersSize);
for (int i = 0; i < parametersSize; ++i) {
// 转换参数,处理 java8 时间
parameters.add(getJdbcParameter(statement.getParameter(i)));
}
String dbType = statement.getConnectionProxy().getDirectDataSource().getDbType();
String formattedSql = SQLUtils.format(sql, DbType.of(dbType), parameters, FORMAT_OPTION);
printSql(formattedSql, statement);
}

private static Object getJdbcParameter(JdbcParameter jdbcParam) {
if (jdbcParam == null) {
return null;
}
Object value = jdbcParam.getValue();
// 处理 java8 时间
if (value instanceof TemporalAccessor) {
return value.toString();
}
return value;
}

private static void printSql(String sql, StatementProxy statement) {
// 打印 sql
String sqlLogger = "\n\n======= Sql Logger ======================" +
"\n{}" +
"\n======= Sql Execute Time: {} =======\n";
log.info(sqlLogger, sql.trim(), StringUtil.format(statement.getLastExecuteTimeNano()));
}

}
Loading

0 comments on commit 8c3a3ca

Please sign in to comment.