纯SpringMVC框架下如何实现请求全信息日志记录?
Great question! When working with plain Spring MVC (without Spring Boot's auto-config magic), you won't get out-of-the-box request logging like you do in Boot—but there are Spring-native solutions you can use, plus flexible custom options if you need more control. Let's break this down:
1. Use Spring's Built-in CommonsRequestLoggingFilter
This is the easiest and most "Spring-native" approach—no extra dependencies needed, just leveraging what's already in the spring-web module.
How to Configure It
You'll need to register this filter explicitly (since there's no Spring Boot auto-config to do it for you). Here's how to set it up with both Java and XML configuration:
Java Configuration
Create a @Configuration class (or add to your existing Spring MVC config) to define the filter bean:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.filter.CommonsRequestLoggingFilter; @Configuration public class RequestLoggingConfig { @Bean public CommonsRequestLoggingFilter requestLoggingFilter() { CommonsRequestLoggingFilter loggingFilter = new CommonsRequestLoggingFilter(); // Enable logging of request details you care about loggingFilter.setIncludeClientInfo(true); // Logs client IP, user agent loggingFilter.setIncludeQueryString(true); // Logs URI query parameters loggingFilter.setIncludePayload(true); // Logs request body loggingFilter.setMaxPayloadLength(10000); // Limit payload size to avoid huge logs loggingFilter.setIncludeHeaders(false); // Optional: set to true if you need headers too return loggingFilter; } }
XML Configuration
If you're using XML-based Spring config, add this to your dispatcher-servlet.xml (or root context):
<bean id="requestLoggingFilter" class="org.springframework.web.filter.CommonsRequestLoggingFilter"> <property name="includeClientInfo" value="true"/> <property name="includeQueryString" value="true"/> <property name="includePayload" value="true"/> <property name="maxPayloadLength" value="10000"/> <property name="includeHeaders" value="false"/> </bean> <!-- Map the filter to all incoming requests --> <filter-mapping> <filter-name>requestLoggingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Critical Note: Log Level Setup
This filter logs details at the DEBUG level, so you need to configure your logging framework (Logback, Log4j, etc.) to enable DEBUG logs for the filter class. For example, in Logback:
<logger name="org.springframework.web.filter.CommonsRequestLoggingFilter" level="DEBUG"/>
Why This Works
The filter uses ContentCachingRequestWrapper under the hood, which caches the request body so it can be read for logging without breaking subsequent request processing (since the original input stream can only be read once).
2. Create a Custom Filter (For Full Control)
If you need more flexibility—like custom log formatting, adding extra context, or filtering sensitive data—you can create your own filter by extending OncePerRequestFilter (Spring's base class for filters that run once per request):
import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets; import org.springframework.util.StreamUtils; import org.springframework.web.util.ContentCachingRequestWrapper; public class CustomRequestLoggingFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // Capture request details String uri = request.getRequestURI(); String queryString = request.getQueryString(); String clientIp = request.getRemoteAddr(); // For proxied requests, you might need to get X-Forwarded-For header: // String clientIp = request.getHeader("X-Forwarded-For") != null ? request.getHeader("X-Forwarded-For") : request.getRemoteAddr(); String userAgent = request.getHeader("User-Agent"); // Wrap request to cache body for logging ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request); filterChain.doFilter(wrappedRequest, response); // Let request proceed first // Read cached request body String requestBody = new String(wrappedRequest.getContentAsByteArray(), StandardCharsets.UTF_8); // Log with your preferred format/level logger.info("Incoming Request - URI: {}, Query: {}, Client IP: {}, User Agent: {}, Body: {}", uri, queryString, clientIp, userAgent, requestBody); } }
Then register this filter just like the built-in one (via Java or XML config).
Why enableLoggingRequestDetails Didn't Work
That configuration property is specific to Spring Boot—it's part of Boot's auto-configuration for request logging, which automatically sets up CommonsRequestLoggingFilter when enabled. In plain Spring MVC, there's no auto-config infrastructure to pick up that property, so setting it has no effect.
Final Recommendations
- Start with
CommonsRequestLoggingFilterfirst—it's simple, maintained by Spring, and covers all your basic needs. - Use a custom filter only if you need to tweak the log format, redact sensitive data (like passwords in the request body), or add custom context.
内容的提问来源于stack exchange,提问作者guojiubo

