Spring Boot Request Logging, Request/Response Wrappers, OncePerRequestFilter, and AOP Utility Classes
This article explains how Spring Boot's built‑in logging filter, request and response caching wrappers, the OncePerRequestFilter base class, and AOP helper classes such as AopContext, AopUtils, and ReflectionUtils can be configured and used to record, modify, and monitor HTTP traffic and simplify proxy‑based programming.
Spring Boot provides a set of built‑in utilities that help developers efficiently log, wrap, and process HTTP requests and responses, as well as simplify AOP‑related programming.
1. Request Data Logging
Spring Boot includes AbstractRequestLoggingFilter , whose commonly used implementation is CommonsRequestLoggingFilter . By registering this filter, developers can record query strings, payloads, headers, and client information.
@Configuration
public class RequestLoggingConfig {
@Bean
public CommonsRequestLoggingFilter logFilter() {
CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
filter.setIncludeQueryString(true);
filter.setIncludePayload(true);
filter.setIncludeHeaders(true);
filter.setIncludeClientInfo(true);
filter.setAfterMessagePrefix("REQUEST DATA-");
return filter;
}
}Set the logger level to DEBUG for org.springframework.web.filter.CommonsRequestLoggingFilter to see detailed request logs.
2. Request/Response Wrappers
What are they?
Spring provides ContentCachingRequestWrapper and ContentCachingResponseWrapper to cache the request body and response body, allowing multiple reads and post‑processing.
Request Wrapper
ContentCachingRequestWrapper : caches the input stream so the body can be read repeatedly (e.g., for logging).
Response Wrapper
ContentCachingResponseWrapper : caches the output stream so the response can be modified before it is sent to the client.
Typical Use Cases
Request logging (headers, parameters, body).
Modifying request data before it reaches controllers.
Modifying response content (adding headers, signatures, etc.).
Performance testing by caching I/O.
Example: Request Wrapper Filter
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;
@Component
public class RequestWrapperFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
// Example: read body for logging
byte[] body = requestWrapper.getContentAsByteArray();
// ...process body...
filterChain.doFilter(requestWrapper, response);
}
}Example: Response Wrapper Filter
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;
@Component
public class ResponseWrapperFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
filterChain.doFilter(request, responseWrapper);
// Example: add a custom header after processing
byte[] body = responseWrapper.getContentAsByteArray();
responseWrapper.setHeader("X-Signature", "some-signature");
responseWrapper.copyBodyToResponse();
}
}3. OncePerRequestFilter
OncePerRequestFilter is a Spring base class that guarantees a filter runs only once per request, even when the request is forwarded or included.
Single execution prevents duplicate processing.
Built‑in support for request/response wrappers.
Reduces boilerplate code.
Easy to extend by overriding doFilterInternal .
Typical Scenarios
Request logging without duplicate entries.
Pre‑processing or modifying request data.
Post‑processing response data (e.g., adding headers, signatures).
Security checks that should run only once.
Performance monitoring.
Centralized exception handling.
4. AOP Helper Classes ("Three‑Piece Set")
AopContext
Provides access to the current proxy and target objects. Common methods:
getTargetObject() – retrieve the underlying bean.
currentProxy() – obtain the current proxy, useful for self‑invocation scenarios.
public void noTransactionTask(String keyword) {
((YourClass) AopContext.currentProxy()).transactionTask(keyword);
}
@Transactional
void transactionTask(String keyword) {
// business logic
System.out.println(keyword);
}AopUtils
Utility class for AOP‑related operations such as detecting proxy type.
getTargetObject(Object proxy)
isJdkDynamicProxy(Object obj)
isCglibProxy(Object obj)
if (AopUtils.isCglibProxy(myService)) {
System.out.println("This is a CGLIB proxy");
}ReflectionUtils
Convenient wrapper around Java reflection, offering methods to make fields accessible, read/write fields, and invoke methods.
makeAccessible(Field field)
getField(Field field, Object target)
invokeMethod(Method method, Object target, Object... args)
Field field = ReflectionUtils.findField(ExampleBean.class, "mapAttribute");
ReflectionUtils.makeAccessible(field);
Object value = ReflectionUtils.getField(field, bean);
System.out.println(value);These built‑in classes simplify common AOP and reflection tasks in Spring applications.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.