Modify Request in Spring Boot Before Controller with HandlerInterceptor: A Comprehensive Guide
Image by Maxime - hkhazo.biz.id

Modify Request in Spring Boot Before Controller with HandlerInterceptor: A Comprehensive Guide

Posted on

As a Spring Boot developer, you may encounter situations where you need to modify incoming requests before they reach your controllers. Perhaps you want to add a custom header, modify the request body, or even cancel the request altogether. This is where Spring Boot’s HandlerInterceptor comes into play. In this article, we’ll explore how to use HandlerInterceptor to modify requests in Spring Boot before they reach your controllers.

What is a HandlerInterceptor?

A HandlerInterceptor is a powerful tool in Spring Boot that allows you to intercept and modify incoming requests before they reach your controllers. It’s a part of the Spring MVC framework and provides a way to execute code before and after a request is handled by a controller. HandlerInterceptors are typically used for tasks such as authentication, logging, and caching, but they can also be used to modify request headers, bodies, or even cancel the request altogether.

Creating a HandlerInterceptor

To create a HandlerInterceptor, you need to implement the `HandlerInterceptor` interface, which has three methods:

  • `preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)`: This method is called before the request is handled by the controller. It returns a boolean value indicating whether the request should proceed.
  • `postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)`: This method is called after the request has been handled by the controller, but before the response is sent back to the client.
  • `afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)`: This method is called after the request has been handled by the controller and the response has been sent back to the client.

Here’s an example of a simple HandlerInterceptor that logs the request URI and method:


public class LoggingInterceptor implements HandlerInterceptor {
  
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    System.out.println("Request URI: " + request.getRequestURI());
    System.out.println("Request Method: " + request.getMethod());
    return true; // Allow the request to proceed
  }
  
  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    // No-op
  }
  
  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    // No-op
  }
}

Registering a HandlerInterceptor

To register a HandlerInterceptor, you need to add it to the Spring Boot application context. You can do this by creating a `WebMvcConfigurer` bean and overriding the `addInterceptors` method:


@Configuration
public class WebConfig implements WebMvcConfigurer {
  
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LoggingInterceptor());
  }
}

This will register the `LoggingInterceptor` with Spring Boot, and it will be executed for every incoming request.

Modifying the Request

Now that we have a HandlerInterceptor registered, let’s see how we can modify the request. One common use case is to add a custom header to the request. We can do this by using the `HttpServletRequest` object in the `preHandle` method:


public class ModifyRequestInterceptor implements HandlerInterceptor {
  
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    request.setAttribute("Custom-Header", "Hello, World!");
    return true;
  }
  
  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    // No-op
  }
  
  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    // No-op
  }
}

In this example, we’re adding a custom header called `Custom-Header` with the value `Hello, World!`. This header will be available in the controller method that handles the request.

Modifying the Request Body

Another common use case is to modify the request body before it reaches the controller. We can do this by using the `HttpServletRequest` object in the `preHandle` method:


public class ModifyRequestBodyInterceptor implements HandlerInterceptor {
  
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    ServletInputStream inputStream = request.getInputStream();
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    IOUtils.copy(inputStream, outputStream);
    String requestBody = outputStream.toString("UTF-8");
    // Modify the request body
    requestBody = requestBody.replace("old_value", "new_value");
    request.setAttribute("RequestBody", requestBody);
    return true;
  }
  
  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    // No-op
  }
  
  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    // No-op
  }
}

In this example, we’re reading the request body as a string, modifying it, and then setting it as an attribute on the request object. This modified request body will be available in the controller method that handles the request.

Cancelling the Request

Sometimes, you may want to cancel the request altogether. You can do this by returning `false` from the `preHandle` method:


public class CancelRequestInterceptor implements HandlerInterceptor {
  
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // Cancel the request if it meets certain conditions
    if (request.getRequestURI().contains("cancel_me")) {
      return false; // Cancel the request
    }
    return true; // Allow the request to proceed
  }
  
  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    // No-op
  }
  
  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    // No-op
  }
}

In this example, we’re cancelling the request if the request URI contains the string `cancel_me`. This will prevent the controller method from being called, and the request will be terminated.

Order of Execution

When you have multiple HandlerInterceptors registered, the order of execution is important. By default, Spring Boot will execute the interceptors in the order they were registered. However, you can control the order of execution by using the `@Order` annotation:


@Order(1)
public class LoggingInterceptor implements HandlerInterceptor {
  // ...
}

@Order(2)
public class ModifyRequestInterceptor implements HandlerInterceptor {
  // ...
}

In this example, the `LoggingInterceptor` will be executed before the `ModifyRequestInterceptor`. This is because the `LoggingInterceptor` has a lower order value.

Conclusion

In this article, we’ve seen how to modify requests in Spring Boot using HandlerInterceptors. We’ve covered how to create a HandlerInterceptor, register it with Spring Boot, and use it to modify the request headers, body, and even cancel the request altogether. By using HandlerInterceptors, you can decouple your request modification logic from your controllers and make your code more modular and reusable.

Method Description
preHandle Called before the request is handled by the controller. Returns a boolean value indicating whether the request should proceed.
postHandle Called after the request has been handled by the controller, but before the response is sent back to the client.
afterCompletion Called after the request has been handled by the controller and the response has been sent back to the client.

I hope this article has been helpful in demonstrating the power of HandlerInterceptors in Spring Boot. With this knowledge, you can now modify requests in a flexible and modular way, making your code more maintainable and efficient.

Frequently Asked Question

Get ready to dive into the world of Spring Boot and uncover the secrets of modifying requests before they reach your controller using HandlerInterceptor!

What is the purpose of HandlerInterceptor in Spring Boot?

HandlerInterceptor is a powerful tool in Spring Boot that allows you to intercept and modify requests before they reach your controller. It provides a way to perform tasks such as authentication, logging, and caching, giving you more control over the request-response cycle.

How do I modify a request using HandlerInterceptor in Spring Boot?

To modify a request using HandlerInterceptor, you need to override the `preHandle` method in your custom HandlerInterceptor class. This method provides access to the HttpServletRequest and HttpServletResponse objects, allowing you to modify the request as needed. Simply return `true` to continue with the request or `false` to stop it.

Can I modify the request body using HandlerInterceptor in Spring Boot?

Yes, you can modify the request body using HandlerInterceptor in Spring Boot. However, you need to be careful when doing so, as the request body can only be read once. You can use a Filter or a wrapper class to modify the request body without consuming it.

How do I register a HandlerInterceptor in Spring Boot?

To register a HandlerInterceptor in Spring Boot, you need to add the `@Component` annotation to your custom HandlerInterceptor class. Then, you can use the `WebMvcConfigurer` interface to add the interceptor to the Spring Boot application context. Alternatively, you can use the `@Configuration` annotation and register the interceptor programmatically.

Can I use HandlerInterceptor to modify requests for specific controllers or methods?

Yes, you can use HandlerInterceptor to modify requests for specific controllers or methods in Spring Boot. You can use the `addPathPatterns` or `excludePathPatterns` methods to specify which controllers or methods the interceptor should apply to. This allows you to fine-tune the interceptor’s behavior and only modify requests that meet specific criteria.

Leave a Reply

Your email address will not be published. Required fields are marked *