有这样的需求在Spring Boot + MyBatis 实现的系统中记录SQL操作用来进行企业审计操作使用。下面我们就来探讨一下如何实现这个需求。
使用MyBatis的内置日志功能
在MyBatis中提供了内置的日志功能,通过这个内置日志功能来实现SQL操作的记录操作,如下所示。
配置log4j2
要使用log4j2就需要在pom.xml文件中添加相关的依赖配置,如下所示。
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.14.1</version>
</dependency>
接下来就是配置log4j2.xml文件,如下所示。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>
</Console>
<File name="File" fileName="logs/mybatis.log" append="false">
<PatternLayout>
<pattern>%d %p %C{1.} [%t] %m%n</pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Logger name="org.mybatis" level="DEBUG" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="File"/>
</Logger>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
最后,需要在SpringBoot的配置文件中开启相关的日志配置,如下所示。
logging.config=classpath:log4j2.xml
配置logback
除了使用log4j2,我们还可以通过logback日志框架来进行记录,需要引入相关的依赖配置,如下所示。
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
配置logback-spring.xml文件
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/mybatis.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/mybatis-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.mybatis" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</logger>
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
在SpringBoot配置文件中开启logback日志配置,如下所示。
logging.config=classpath:logback-spring.xml
使用MyBatis提供的插件接口
当然我们也可以通过MyBatis提供的插件机制来记录SQL操作,如下所示。
首先,我们先来创建一个插件配置类如下所示。
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import java.sql.Statement;
import java.util.Properties;
@Intercepts({
@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),
@Signature(type = StatementHandler.class, method = "update", args = {Statement.class}),
@Signature(type = StatementHandler.class, method = "batch", args = {Statement.class})
})
public class SqlLogInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
String sql = statementHandler.getBoundSql().getSql();
System.out.println("Executing SQL: " + sql); // 或者使用日志框架记录
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
// 可以从配置文件中读取一些配置
}
}
然后需要在MyBatis的配置文件中将这个插件注入到其中,如下所示。
<plugins>
<plugin interceptor="com.example.demo.SqlLogInterceptor"/>
</plugins>
最后,需要在SpringBoot的配置文件中,引入MyBatis的配置如下所示。
mybatis.config-location=classpath:mybatis-config.xml
使用Spring AOP进行日志记录
除了上面的两种方式之外,我们还可以通过AOP切面操作来实现SQL日志的记录,如下所示。
首先先来定义一个切面操作类,如下所示。
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class SqlLogAspect {
@Before("execution(* org.apache.ibatis.executor.statement.StatementHandler.*(..))")
public void logBefore() {
System.out.println("Before executing SQL"); // 或者使用日志框架记录
}
@AfterReturning("execution(* org.apache.ibatis.executor.statement.StatementHandler.*(..))")
public void logAfter() {
System.out.println("After executing SQL"); // 或者使用日志框架记录
}
}
然后需要在SpringBoot的主启动类上通过@EnableAspectJAutoProxy注解来开启日志记录操作。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@SpringBootApplication
@EnableAspectJAutoProxy
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
总结
以上的这些方法都可以帮助我们实现SpringBoot+MyBatis记录SQL查询日志操作,当然具体使用那种方式还是要根据具体的业务需求来进行选择。