springboot集成mybatisplus-sql日志自定义控制是否打印-亲测可用
因项目个别请求频率极高,需要自定义细粒度控制接口不打印执行sql,不影响别的接口打印执行sql,这里记录下实现。
·
前言
因项目个别请求频率极高,需要自定义细粒度控制接口不打印执行sql,不影响别的接口打印执行sql,这里记录下实现。
步骤一
关闭项目本身sql日志打印
#关闭mybatis-plus日志打印 mybatis-plus: # configuration: # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # SQL 打印#项目使用了分表分库插件shardingsphere 需要关闭日志 shardingsphere: mode: type: Standalone # 显式指定模式 props: sql-show: false #sql日志#项目使用logging日志打印设置 logging: level: root: info
步骤二
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
@Autowired
private MybatisPluginProperties mybatisPluginProperties;
/**
* 添加分页插件
*/
/*
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加
// interceptor.addInnerInterceptor(new MybatisPlusAllSqlLog());
// 这里添加 SQL 性能分析插件,用来打印 SQL 和执行时间
// 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
return interceptor;
}
*/
/**
* 自定义细粒度控制sql打印
* @return
*/
@Bean
public MybatisSqlLogInterceptor mybatisSqlLogInterceptor() {
MybatisSqlLogInterceptor interceptor = new MybatisSqlLogInterceptor();
interceptor.setSlownessThreshold(mybatisPluginProperties.getSqlLog().getSlownessThreshold());
return interceptor;
}
}
MybatisUtils类
import lombok.experimental.UtilityClass;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandlerRegistry;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@UtilityClass
public class MybatisUtils {
private static final Pattern PARAMETER_PATTERN = Pattern.compile("\\?");
public String getSql(MappedStatement mappedStatement, Invocation invocation) {
Object parameter = null;
if (invocation.getArgs().length > 1) {
parameter = invocation.getArgs()[1];
}
BoundSql boundSql = mappedStatement.getBoundSql(parameter);
Configuration configuration = mappedStatement.getConfiguration();
return resolveSql(configuration, boundSql);
}
private static String resolveSql(Configuration configuration, BoundSql boundSql) {
Object parameterObject = boundSql.getParameterObject();
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
if (!parameterMappings.isEmpty() && parameterObject != null) {
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(resolveParameterValue(parameterObject)));
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
Matcher matcher = PARAMETER_PATTERN.matcher(sql);
StringBuffer sqlBuffer = new StringBuffer();
for (ParameterMapping parameterMapping : parameterMappings) {
String propertyName = parameterMapping.getProperty();
Object obj = null;
if (metaObject.hasGetter(propertyName)) {
obj = metaObject.getValue(propertyName);
} else if (boundSql.hasAdditionalParameter(propertyName)) {
obj = boundSql.getAdditionalParameter(propertyName);
}
if (matcher.find()) {
matcher.appendReplacement(sqlBuffer, Matcher.quoteReplacement(resolveParameterValue(obj)));
}
}
matcher.appendTail(sqlBuffer);
sql = sqlBuffer.toString();
}
}
return sql;
}
private static String resolveParameterValue(Object obj) {
if (obj instanceof CharSequence) {
return "'" + obj + "'";
}
if (obj instanceof Date) {
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
return "'" + formatter.format(obj) + "'";
}
return obj == null ? "" : String.valueOf(obj);
}
}
MybatisSqlLogInterceptor 类
说明:MyBatis 中,Interceptor 是一个非常重要的接口,它用于在 MyBatis 执行 SQL 操作时对 SQL 执行的过程进行拦截。通过实现 Interceptor 接口,开发者可以在 MyBatis 执行 SQL 的不同阶段(如执行前、执行后、处理结果等)插入自定义的逻辑
执行sql拦截器会拦截根据自定义是否打印sql
import com.baomidou.mybatisplus.core.toolkit.SystemClock;
import com.macro.mall.common.util.RequestUtil;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
@Intercepts({
@Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
@Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class})
})
public class MybatisSqlLogInterceptor implements Interceptor {
private static final Logger log = LoggerFactory.getLogger("MybatisSqlLog");
private Duration slownessThreshold = Duration.ofMillis(1000);
@Override
public Object intercept(Invocation invocation) throws Throwable {
//获取 HttpServletRequest 路径判断是否打印 或 过滤器 判断接口是否打印状态放入 如下代码
/*
//1.获取设置是否打印请求日志
public static Boolean getReqLogStatus(HttpServletRequest request) {
Boolean flag = true;
Object attribute = request.getSession().getAttribute(CommonDataConstant.REQ_LOG_STATUS);
if(attribute!=null){
flag = false;
}
return flag;
}
//2.设置是否打印请求日志
httpServletRequest.getSession().setAttribute(CommonDataConstant.REQ_LOG_STATUS, true);
*/
/*
//3.控制是否打印sql
try{
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if(requestAttributes!=null){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
if(!RequestUtil.getReqLogStatus(request)){
Object results = invocation.proceed();
return results;
}
}
}catch (Exception e){
e.printStackTrace();
log.error(e.getMessage());
}*/
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
String mapperId = mappedStatement.getId();
String originalSql = MybatisUtils.getSql(mappedStatement, invocation);
long start = SystemClock.now();
Object result = invocation.proceed();
long duration = SystemClock.now() - start;
// 当 SQL 执行超过我们设置的阈值,转为 WARN 级别
if (Duration.ofMillis(duration).compareTo(slownessThreshold) < 0) {
log.info("{} execute sql: {} ({} ms)", mapperId, originalSql, duration);
} else {
log.info("{} execute sql took more than {} ms: {} ({} ms)", mapperId, slownessThreshold.toMillis(), originalSql, duration);
}
return result;
}
@Override
public Object plugin(Object target) {
if (target instanceof Executor) {
return Plugin.wrap(target, this);
}
return target;
}
// 设置慢 SQL 阈值,单位为秒
public void setSlownessThreshold(Duration slownessThreshold) {
this.slownessThreshold = slownessThreshold;
}
}
MybatisPluginProperties类
import lombok.Data;
import org.springframework.context.annotation.Configuration;
import java.time.Duration;
@Configuration
@Data
public class MybatisPluginProperties {
private final SqlLog sqlLog = new SqlLog();
@Data
public static class SqlLog {
private boolean enabled = true;
private Duration slownessThreshold = Duration.ofMillis(1000);
}
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)