Implement a HandlerInterceptor in SpringBoot to obtain the incoming parameters of the request and convert them into Java objects.
Method 1: Interceptor and filter
1. Design ideas
In web development, when an HTTP request is sent to the server, Spring will process the request through a chain, which includes many components, such as: an interceptor (HandlerInterceptor
), filter (Filter
), controller (Controller), parameter parser (such as Spring MVC's@RequestParam
or@RequestBody
etc. annotations) etc.
Issues with input streams
When the client passesPOST
When requesting to send data, the data is usually contained in the request body (such as form data or JSON data). Spring'sHttpServletRequest
ProvidedgetInputStream()
Method to read data in the request body.
question: ()
Only read once. That is, when you call it in the interceptorgetInputStream()
When reading data, the stream is consumed, and subsequent components (for example, Spring's parameter parser) are called again.getInputStream()
The data cannot be read because the stream has been closed.
Solution
The idea to solve this problem is: when reading the data of the request body in the interceptor, it does not directly come fromHttpServletRequest
read in , but wrapper (HttpServletRequestWrapper
) method to re-implementgetInputStream()
, cache the read data to ensure that the subsequent processing chain can still access the content of the request body.
2. How to implement it
- Create a
HttpServletRequestWrapper
Class: It will be rewritegetInputStream()
Method, allowing stream data to be read multiple times. The contents of the request body are cached through this class. - Create a
Filter
: Used for packaging requests, willHttpServletRequest
Package it into our ownHttpServletRequestWrapper
。 -
Get request body in interceptor:exist
HandlerInterceptor
Get the request body and parse it.
3. Implementation steps
3.1 Create HttpServletRequestWrapper
This class mainly serves to cache the request body content and rewrite it.getInputStream()
, allowing it to read multiple times.
import ; import ; import ; import ; import ; public class CachedBodyHttpServletRequestWrapper extends HttpServletRequestWrapper { private byte[] requestBody; public CachedBodyHttpServletRequestWrapper(HttpServletRequest request) throws IOException { super(request); // Read data from InputStream and cache the request body content InputStream inputStream = (); = (); // Read data from the stream into a byte array } @Override public InputStream getInputStream() throws IOException { // Return cached data return new ByteArrayInputStream(requestBody); } public byte[] getRequestBody() { return requestBody; } }
3.2 Create a Filter to wrap HttpServletRequest
The function of this filter is to put the originalHttpServletRequest
Replace with our customizedCachedBodyHttpServletRequestWrapper
。
import ; import ; import ; import ; import ; import ; import ; import ; import ; @WebFilter("/*") // This filter intercepts all requestspublic class RequestWrapperFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // Initialization operation } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // Only wrap HttpServletRequest if (request instanceof HttpServletRequest) { CachedBodyHttpServletRequestWrapper wrappedRequest = new CachedBodyHttpServletRequestWrapper((HttpServletRequest) request); // Pass the wrapped request to the next filter (wrappedRequest, response); } else { // No processing is done to non-HttpServletRequest requests (request, response); } } @Override public void destroy() { // Destruction operation } }
3.3 Create an interceptor HandlerInterceptor to handle request parameters
Next, get the request body in Spring's interceptor and parse it into a Java object. This interceptor will intercept before the request enters the controller.
import ; import ; import ; import ; public class RequestBodyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { if (request instanceof CachedBodyHttpServletRequestWrapper) { // Get the packaged request body CachedBodyHttpServletRequestWrapper wrappedRequest = (CachedBodyHttpServletRequestWrapper) request; String requestBody = new String((), "UTF-8"); // Print or process the requested content ("Request Body: " + requestBody); // Convert the request body into a Java object MyRequestObject myRequestObject = new ObjectMapper().readValue(requestBody, ); ("Parsed Java Object: " + myRequestObject); } return true; // Return true, indicating that the request is continued } }
3.4 Register Interceptors and Filters
- Register in Spring Boot
Filter
:
Tip: In Spring Boot project,Filter
It will be automatically registered in the application context and may not be manually registered.
import ; import ; import ; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<RequestWrapperFilter> loggingFilter() { FilterRegistrationBean<RequestWrapperFilter> registrationBean = new FilterRegistrationBean<>(); (new RequestWrapperFilter()); ("/api/*"); // Configure the intercepted URL as needed here return registrationBean; } }
- Register in Spring Boot
HandlerInterceptor
:
import ; import ; import ; import ; import ; @Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private RequestBodyInterceptor requestBodyInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { (requestBodyInterceptor).addPathPatterns("/api/*"); // Configure the path as needed } }
4. Summary
Through the above steps, you can implement a single read multiple times()
The mechanism of data. The basic idea is:
- Create a
HttpServletRequestWrapper
Classes to cache request body content; - pass
Filter
Come to packHttpServletRequest
; - exist
HandlerInterceptor
Get the request body and process it.
In this way, both in the interceptor and subsequent parameter analysis process, the request volume data can be accessed multiple times.
Method 2: Use the wrapper class ContentCachingRequestWrapper in the interceptor
In an HTTP request,HttpServletRequest
The request body (JSON data in the POST request) is a one-time stream. After reading it once, if there is no special processing, it cannot be read again.
ContentCachingRequestWrapper
It is a packaging class provided by the Spring framework, and its function is to "package" the originalHttpServletRequest
Object, so that the content of the request body can be read multiple times.
useContentCachingRequestWrapper
, save the HttpServletRequestWrapper and RequestWrapperFilter created in Method One.
import ; import ; import ; import ; public class RequestBodyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { if ((())) { // Package the request so that it can read the request body multiple times ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request); // Read the request body, clearly specify the character encoding as UTF-8 String requestBody = new String((), "UTF-8"); // Print or process the requested content ("Request Body: " + requestBody); // Convert the request body into a Java object MyRequestObject myRequestObject = new ObjectMapper().readValue(requestBody, ); ("Parsed Java Object: " + myRequestObject); } return true; // Return true, indicating that the request is continued } }
Summarize
ContentCachingRequestWrapper
It is a very useful tool that allows cache and read request body content multiple times, especially when processing request body data in an interceptor, it is very effective.
This is the article about how to use an interceptor to obtain the requested parameters and convert them into Java objects. For more related interceptors to obtain requested parameters and convert Java objects, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!