先看效果
javascript
2025-08-26 09:52:19.834 [http-nio-10003-exec-10] INFO c.x.c.logging.RequestLoggingFilter - HTTP请求: {headers={content-length=213, host=192.168.31.149:10003, content-type=application/json, connection=keep-alive, accept-encoding=gzip, deflate, br, user-agent=Apifox/1.0.0 (https://apifox.com), accept=*/*}, 调用方式=POST, 客户端IP=192.168.31.149, 接口路径=/test/exam/addData, body={
"classificationId": 232,
"examRecordId": 1223,
"userId": 234
}, 传递参数=null}
2025-08-26 10:00:48.678 [http-nio-10003-exec-2] WARN com.zaxxer.hikari.pool.PoolBase - HikariPool-1 - Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl@2871c902 (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.
2025-08-26 10:00:48.737 [http-nio-10003-exec-2] INFO c.x.c.logging.RequestLoggingFilter - HTTP请求: {headers={host=192.168.31.149:10003, connection=keep-alive, accept-encoding=gzip, deflate, br, user-agent=Apifox/1.0.0 (https://apifox.com), accept=*/*}, 调用方式=GET, 客户端IP=192.168.31.149, 接口路径=/test/banner/list, 传递参数=null}
一、配置Maven依赖
XML
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis-Flex -->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.8.6</version>
</dependency>
<!-- Logback JSON输出 -->
<dependency>
<groupId>ch.qos.logback.contrib</groupId>
<artifactId>logback-json-classic</artifactId>
<version>0.1.5</version>
</dependency>
<dependency>
<groupId>ch.qos.logback.contrib</groupId>
<artifactId>logback-jackson</artifactId>
<version>0.1.5</version>
</dependency>
<!-- 用于获取请求体 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
二、配置properties资源包
生产环境等相关自己按需要配置
javascript
#logging
logging.level.com.mybatisflex:INFO
三、新增:src/main/resources/logback-spring.xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
<jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
<prettyPrint>true</prettyPrint>
</jsonFormatter>
<timestampFormat>yyyy-MM-dd' 'HH:mm:ss.SSS</timestampFormat>
<appendLineSeparator>true</appendLineSeparator>
</layout>
</encoder>
</appender>
<appender name="PLAIN_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 针对请求日志使用JSON格式 -->
<logger name="com.xiaoqiu.RequestLoggingFilter" level="INFO">
<appender-ref ref="CONSOLE" />
</logger>
<!-- MyBatis-Flex SQL日志 -->
<logger name="com.mybatis" level="INFO" />
<!-- 根日志记录器 -->
<root level="INFO">
<appender-ref ref="PLAIN_CONSOLE" />
</root>
</configuration>
四、新增:com/你的包路径/config/requestLoggingFilter
java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@Component
public class RequestLoggingFilter extends OncePerRequestFilter {
private static final Logger logger = LoggerFactory.getLogger(RequestLoggingFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 包装请求和响应以支持多次读取
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);
try {
filterChain.doFilter(wrappedRequest, wrappedResponse);
} finally {
// 记录请求信息
logRequest(wrappedRequest);
// 记录响应信息(可选)
logResponse(wrappedResponse);
// 将响应内容写回客户端
wrappedResponse.copyBodyToResponse();
}
}
private void logRequest(ContentCachingRequestWrapper request) {
Map<String, Object> logData = new HashMap<>();
// 基本信息
logData.put("调用方式", request.getMethod());
logData.put("接口路径", request.getRequestURI());
logData.put("传递参数", request.getQueryString());
logData.put("客户端IP", request.getRemoteAddr());
// 请求头
Map<String, String> headers = new HashMap<>();
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
headers.put(headerName, request.getHeader(headerName));
}
logData.put("headers", headers);
// 请求参数
Map<String, String[]> params = request.getParameterMap();
if (!params.isEmpty()) {
logData.put("请求参数", params);
}
// 请求体(JSON)
byte[] content = request.getContentAsByteArray();
if (content.length > 0) {
try {
String body = new String(content, request.getCharacterEncoding());
logData.put("body", body);
} catch (UnsupportedEncodingException e) {
logger.warn("无法解析请求正文", e);
}
}
logger.info("客户端请求: {}", logData);
}
private void logResponse(ContentCachingResponseWrapper response) {
// 可选的响应日志记录逻辑
}
}