mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-08 12:39:05 +08:00
✨ DruidSqlLogFilter Mybatis 输出日志格式化处理
This commit is contained in:
1 parent
f595cda94e
commit
80c6edc221
4 files changed
+207
-5
No files matched your search
@@ -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>
|
||||
|
||||
+23
@@ -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;
|
||||
|
||||
}
|
||||
+162
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+15
-4
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user