Backend Development 8 min read

Modifying SpringBoot Request Body with Filters, AOP, and Interceptors

This article demonstrates three practical methods to transform the HTTP request body in a SpringBoot 3.2.5 application before it reaches the controller—using a custom Filter, a RequestBodyAdvice‑based AOP approach, and a HandlerInterceptor—complete with code examples, explanations, and testing results.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Modifying SpringBoot Request Body with Filters, AOP, and Interceptors

1. Introduction

Modifying the request body is often required for data preprocessing and security reasons. In web applications the client‑sent data may not match the format expected by the backend, may contain profanity, be incomplete, or include sensitive information. Changing the body before it reaches the controller allows formatting, validation, and sanitization, promoting loose coupling and reducing development effort.

2. Practical Examples

2.1 Prepare the API

<code>public class Article {
  private String title;
  private String content;
  // getters, setters
}

@RestController
@RequestMapping("/modifybody")
public class ModifyBodyController {

  @PostMapping
  public Article save(@RequestBody Article article) {
    return article;
  }
}
</code>

The endpoint simply receives an Article object without any additional processing.

2.2 Implement with a Filter

A servlet filter is an ideal place to handle cross‑cutting concerns such as request‑body modification. The diagram below shows the filter workflow.

The filter wraps the original HttpServletRequest so that the body can be read multiple times.

<code>@Component
@Order(1)
public static class EscapeHtmlFilter implements Filter {
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
      throws IOException, ServletException {
    filterChain.doFilter(new EscapeHtmlRequestWrapper((HttpServletRequest) servletRequest), servletResponse);
  }
}
</code>

The wrapper performs HTML escaping and overrides getInputStream and getReader to return the sanitized content.

<code>public static class EscapeHtmlRequestWrapper extends HttpServletRequestWrapper {
  private String body = null;
  public EscapeHtmlRequestWrapper(HttpServletRequest request) throws IOException {
    super(request);
    this.body = HtmlUtils.escapeHtml(request);
  }
  public ServletInputStream getInputStream() throws IOException {
    final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
    ServletInputStream servletInputStream = new ServletInputStream() {
      @Override
      public int read() throws IOException {
        return byteArrayInputStream.read();
      }
      // other methods use defaults
    };
    return servletInputStream;
  }
  public BufferedReader getReader() {
    try {
      return new BufferedReader(new InputStreamReader(this.getInputStream()));
    } catch (IOException e) {}
    return null;
  }
}
</code>

After deploying the filter, a test request shows that the &lt;script&gt; tag has been removed.

2.3 Implement with AOP (RequestBodyAdvice)

Using @RestControllerAdvice together with RequestBodyAdvice allows interception of the request body for all REST controllers.

<code>@RestControllerAdvice
public class EscapeHtmlBodyAdvice implements RequestBodyAdvice {
  public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
      Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
    InputStream is = inputMessage.getBody();
    return new HttpInputMessage() {
      public InputStream getBody() throws IOException {
        return new ByteArrayInputStream(HtmlUtils.escapeHtml(is).getBytes(StandardCharsets.UTF_8));
      }
      public HttpHeaders getHeaders() {
        return inputMessage.getHeaders();
      }
    };
  }

  public boolean supports(MethodParameter methodParameter, Type targetType,
      Class<? extends HttpMessageConverter<?>> converterType) {
    return true;
  }

  public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
      Class<? extends HttpMessageConverter<?>> converterType) {
    return body;
  }

  public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
      Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
    return body;
  }
}
</code>

Note: This technique does not involve true AOP proxy creation; it simply processes the body before deserialization.

2.4 Implement with an Interceptor

Spring MVC interceptors can also intercept incoming HTTP requests. The diagram below illustrates the interceptor flow.

<code>public static class EscapeHtmlRequestInterceptor implements HandlerInterceptor {
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    EscapeHtmlRequestWrapper htmlEscapeRequestWrapper = new EscapeHtmlRequestWrapper(request);
    // further processing can be added here
    return HandlerInterceptor.super.preHandle(htmlEscapeRequestWrapper, response, handler);
  }
}

@Component
public class WebMvcConfiguration implements WebMvcConfigurer {
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new EscapeHtmlRequestInterceptor()).addPathPatterns("/**");
  }
}
</code>

A test request results in a 400 error, demonstrating that the interceptor approach cannot modify the request body because the body stream is already consumed.

In summary, the filter‑based solution and the RequestBodyAdvice approach successfully modify the request body, while the interceptor method fails due to the single‑read nature of the request stream.

JavaaopInterceptorSpringBootfilterRequestBody
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.