✨ DruidSqlLogFilter Mybatis 输出日志格式化处理

This commit is contained in:
lbw committed 2021-06-03 15:56:51 +08:00
1 parent f595cda94e
commit 80c6edc221
4 files changed
+207 -5

No files matched your search

+7 -1
View File
@@ -39,11 +39,17 @@
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-core</artifactId>
</dependency>
<!--mybatis plus extension,包含了mybatis plus core-->
<!--mybatis plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</dependency>
<!-- druid 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<optional>true</optional>
</dependency>
<!--安全依赖获取上下文信息-->
<dependency>
<groupId>com.pig4cloud</groupId>
@@ -0,0 +1,23 @@
package com.pig4cloud.pigx.common.data.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
/**
* Mybatis 配置
*
* @author lengleng
* @date 2021/6/3
*/
@Data
@RefreshScope
@ConfigurationProperties("pigx.mybatis")
public class PigxMybatisProperties {
/**
* 是否打印可执行 sql
*/
private boolean showSql = true;
}
@@ -0,0 +1,162 @@
/*
* 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 com.pig4cloud.pigx.common.data.mybatis;
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 com.pig4cloud.pigx.common.data.config.PigxMybatisProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.sql.SQLException;
import java.time.temporal.TemporalAccessor;
import java.util.ArrayList;
import java.util.List;
/**
* 打印可执行的 sql 日志
*
* <p>
* 参考:https://jfinal.com/share/2204
* </p>
*
* @author L.cm
*/
@Slf4j
@RequiredArgsConstructor
public class DruidSqlLogFilter extends FilterEventAdapter {
private static final SQLUtils.FormatOption FORMAT_OPTION = new SQLUtils.FormatOption(false, false);
private final PigxMybatisProperties properties;
@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.isShowSql()) {
return;
}
// 是否开启调试
if (!log.isInfoEnabled()) {
return;
}
// 打印可执行的 sql
String sql = statement.getBatchSql();
// sql 为空直接返回
if (StringUtils.isEmpty(sql)) {
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(), format(statement.getLastExecuteTimeNano()));
}
/**
* 格式化执行时间,单位为 ms 和 s,保留三位小数
* @param nanos 纳秒
* @return 格式化后的时间
*/
private static String format(long nanos) {
if (nanos < 1) {
return "0ms";
}
double millis = (double) nanos / (1000 * 1000);
// 不够 1 ms,最小单位为 ms
if (millis > 1000) {
return String.format("%.3fs", millis / 1000);
}
else {
return String.format("%.3fms", millis);
}
}
}
@@ -17,13 +17,10 @@
package com.pig4cloud.pigx.common.data.mybatis;
import java.util.List;
import javax.sql.DataSource;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.pig4cloud.pigx.common.data.config.PigxMybatisProperties;
import com.pig4cloud.pigx.common.data.datascope.DataScopeHandle;
import com.pig4cloud.pigx.common.data.datascope.DataScopeInnerInterceptor;
import com.pig4cloud.pigx.common.data.datascope.DataScopeSqlInjector;
@@ -36,11 +33,15 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.sql.DataSource;
import java.util.List;
/**
* @author lengleng
* @date 2020-02-08
@@ -48,6 +49,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@ConditionalOnBean(DataSource.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(PigxMybatisProperties.class)
public class MybatisPlusConfiguration implements WebMvcConfigurer {
/**
@@ -110,4 +112,13 @@ public class MybatisPlusConfiguration implements WebMvcConfigurer {
return new DataScopeSqlInjector();
}
/**
* SQL 日志格式化
* @return DruidSqlLogFilter
*/
@Bean
public DruidSqlLogFilter sqlLogFilter(PigxMybatisProperties properties) {
return new DruidSqlLogFilter(properties);
}
}