先看效果
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依赖
<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资源包
生产环境等相关自己按需要配置
#logging
logging.level.com.mybatisflex:INFO
三、新增:src/main/resources/logback-spring.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
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);@Overrideprotected 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) {// 可选的响应日志记录逻辑}
}