欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

springboot+mybatis 写一个记录sql及sql执行时间的日志拦截类

程序员文章站 2022-06-12 16:10:11
...

日志是springboot自带的org.slf4j类型的日志
1、logback.xml 日志配置文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="3 seconds">
	<property name="LOG_HOME" value="temp/logs">
	<appender name="CONSOLE-LOGGER" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<charset>UTF-8</charset>
			<Pattern>%d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] %level %logger{200}.%M:%line - %msg%n</Pattern>
					
		</encoder>
	
	</appender>
	
	<appender name="FILE-LOGGER" class="ch.qos.logback.classic.sift.SiftingAppender">
		<discriminator>
			<key>logFileName</key>
			<defaultValue>testLog</defaultValue>
		</discriminator>
		<sift>
			<appender name="FILE-${logFileName}" class="ch.qos.logback.core.rolling.RollingFileAppender">
				<file>${LOG_HOME}/${logFileName}.log</file>
				<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
					<Pattern>
						%d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] %level %logger{200}.%M:%line -%msg%n
					</Pattern>
				</encoder>
				
			<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
				<FileNamePattern>${LOG_HOME}/${logFileName}.%d{yyyy-MM-dd}.log</FileNamePattern>
				<!--设置最多保留20天  -->
				<maxHistory>20</maxHistory>
			
			</rollingPolicy>
				
			</appender>
		</sift>
	</appender>
	
	<appender>
		<discriminator>
			<key>sqlFileName</key>
			<defaultValue>testSql</defaultValue>
		</discriminator>
			<sift>
			<appender name="FILE-${logFileName}" class="ch.qos.logback.core.rolling.RollingFileAppender">
				<file>${LOG_HOME}/${logFileName}.log</file>
				<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
					<Pattern>
						%d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] %level %logger{200}.%M:%line -%msg%n
					</Pattern>
				</encoder>
				
			<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
				<FileNamePattern>${LOG_HOME}/${logFileName}.%d{yyyy-MM-dd}.log</FileNamePattern>
				<!--设置最多保留20天  -->
				<maxHistory>20</maxHistory>
			
			</rollingPolicy>
				
			</appender>
		</sift>
	</appender>
	
	<root level="info">
		<appender-ref ref="FILE-LOGGER"></appender-ref>
		<appender-ref ref="CONSOLE-LOGGER"></appender-ref>
		
	</root>
	
	<logger name="com.clj" level="debug" additivity="false">
		<appender-ref ref="FILE-LOGGER"></appender-ref>
		<appender-ref ref="CONSOLE-LOGGER"></appender-ref>
	</logger>

  	
	<logger name="java.sql" level="debug" additivity="false">
		<appender-ref ref="FILE-LOGGER"></appender-ref>
		<appender-ref ref="CONSOLE-LOGGER"></appender-ref>
	</logger>
	
	<logger name="sqlLog" level="info" additivity="false">
		<appender-ref ref="SQL-LOGGER"></appender-ref>
	</logger>
	</property>
</configuration>

2、springboot application.yml

在这里插入代码片server:
  port:8080
  tomcat:
    uri-encoding:UTF-8
spring:
  profiles:
  	active:dev
  http:
  	encoding:
  	  force:true
  	  charset:UTF-8
  	  enabled:true
  application:
    name:myTest
 datasource:
 druid:
  driver-class-name:com.ibm.db2.jcc.DB2Driver
  url:jdbc:db2://~~~~~~~~~~~~~~~~~~~~;
  username:~~
  password:~~
  initial-size:5
  min-idle:5
  max-active:20
  max-wait:60000
  time-between-eviction-runs-millis:60000
  min-evictable-idle-time-mills:30000
  validation-query:select 1 from sysibm,sysdummy 1
  test-while-idle:true
  test-on-borrow:false
  test-on-return:false
  pool-prepared-statements:true
  max-pool-prepared-statement-per-connection-size:20
  filters:stat,wall,slf4j
  connection-properties:druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
  use-global-data-source-stat:true
  filter:
    config:
       enabled:true
 web-stat-filter:
     enabled:true
  start-view-servlet:
     enabled:true
mybatis:
  typeAliasesPackage:com.clj.model
  mapperLocations:classpath:mapper/*Mapper.xml
  configuration:
    map-undersore-to-camel-case:true
pagehelper:
  reasonable:true
  support-methods-arguments:true
  params:count = countsql
eureka:
  client:
    register-with-eureka:false
    fetch-registry:false
    
management:
  endpoints:
    web:
      exposure:
        include:info,health,loggers

3、日志打印时间戳转毫秒String

package interceptor;

import java.text.SimpleDateFormat;

public class SimpleDateFormatUtil {
	public static String getStringMillers(long date){
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssS");
		return simpleDateFormat.format(date);
	}
}

4、SQL拦截器,日志打印sql及执行时间打印

package interceptor;


import java.beans.Statement;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.omg.CORBA.PRIVATE_MEMBER;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import io.swagger.annotations.Info;

@Intercepts({@Signature(type=StatementHandler.class,method="query",args={
		Statement.class,ResultHandler.class
})})
@Component
@Configuration
public class SQLInterceptor implements Interceptor{
	private static final Logger logger = LoggerFactory.getLogger("sqlLog");
	private static final int INFO = 2;
	private static final int ERROR = 1;
	
	@Override
	public Object intercept(Invocation invocation) throws Throwable{
		StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
		BoundSql boundSql = statementHandler.getBoundSql();
		String sql = boundSql.getSql();
		//获取当前执行的sql
		logger.info("mybatis interceptor sql:{"+sql+"}");
		long _begin = logTime("beginTime");
		Object object = null;
		try{
			object = invocation.proceed();
		}catch (Throwable e) {
			if(e instanceof SQLException){
				logTime(ERROR,"endTime with SQLException",_begin);
			}else{
				logTime(ERROR,"endTime with Throwable",_begin);
			}
			throw e;	
		}
		logTime("endTime",_begin);
		return object;
	}
	
	private long logTime(String tStr){
		return logTime(INFO,tStr,0);
	}
	
	private long logTime(int lvl,String tStr){
		return logTime(lvl,tStr,0);
	}
	
	private long logTime(String tStr,long _begin){
		return logTime(INFO,tStr,_begin);
		
	}
	

	
	private long logTime(int lvl,String tStr,long _begin){
		String traceClz = traceClz();
		long now = new Date().getTime();
		String nowTime = SimpleDateFormatUtil.getStringMillers(now);
		if(_begin > 0){
			if(lvl == INFO){
				logger.info(traceClz+"["+tStr+":"+nowTime+"timeDiff:"+(now-_begin)+"]");
			}else if(lvl == ERROR){
				logger.error(traceClz+"["+tStr+":"+nowTime+"timeDiff:"+(now-_begin)+"]");
			}
		}else{
			if(lvl ==INFO){
				logger.info(traceClz +"["+tStr+":"+nowTime+"]");
			}else if(lvl == ERROR){
				logger.error(traceClz +"["+tStr+":"+nowTime+"]");
			}
		}
		return now;
	} 
	
	private String traceClz(){
		StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
		StringBuffer stringBuffer = new StringBuffer();
		stringBuffer.append("<"+Thread.currentThread().getId()+">");
		if(stackTrace.length>24){
			int start = 24;
			while(true){
				String clzName = stackTrace[start].getClassName();
				String mtdName = stackTrace[start].getMethodName();
				stringBuffer.append(clzName.substring(clzName.lastIndexOf(".")+1));
				stringBuffer.append(".").append(mtdName.substring(mtdName.lastIndexOf(".")+1));
				if(clzName.indexOf("controller")>-1){
					break;
				}
				start++;
				if(start == stackTrace.length) break;
				stringBuffer.append("<-");
			}
		}
		return stringBuffer.toString();
	}
	
	
	@Override
	public Object plugin(Object arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setProperties(Properties arg0) {
		// TODO Auto-generated method stub
		
	}
	

}