Request Flow
- Embedded Container (Tomcat) receives the request
- It wraps request in a
HttpServletRequest object
- Filter chain is executed
- Request is passed to the
DispatcherServlet in Spring Boot’s MVC architecture.
- Spring MVC
HandlerInterceptors run before the controller (preHandle) and after the controller (postHandle and afterCompletion)
- Then it delegates to appropriate Controller’s method
- References
flowchart TD
Client[Client]
Container[Embedded Servlet Container - Tomcat/Jetty]
Filters[Servlet Filter Chain]
Dispatcher[DispatcherServlet]
Interceptors[HandlerInterceptor]
Controller[Controller / Handler]
Client --> Container
Container --> Filters
Filters --> Dispatcher
Dispatcher --> Interceptors
Interceptors --> Controller
Controller --> Interceptors
Interceptors --> Dispatcher
Dispatcher --> Filters
Filters --> Container
Container --> Client
DispatchServlet
- It maps URLs to specific controller methods and coordinates the flow between other Spring components.
- During application startup, Spring Boot scans all controllers (
@Controller or @RestController) for mappings like @RequestMapping, @GetMapping, etc.
- These mappings are stored in a
HandlerMapping registry at runtime.
Filters
- They intercept requests before reaching Spring DispatcherServlet
- Pre-process request before controller
- Post-process responses returned by the controller
- Clean up after the request is fully completed.
Filter (Interface) > GenericFilterBean (Abstract) > OncePerRequestFilter (Abstract)
- Invoke the next entity in the chain using the FilterChain object ( chain.doFilter() )
- Keep the logic stateless and not depend on other requests
- Use cases
- Authentication: Validating user tokens
- Rate Limiting: Preventing abuse by limiting requests
- Logging: Recording request and response details
- Reference
@Component
@Order(2) // tells order in filter chain
public class RequestResponseLoggingFilter implements Filter {
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
LOG.info(
"Logging Request {} : {}", req.getMethod(),
req.getRequestURI());
// call doFilter to invoke next filter in the chain
chain.doFilter(request, response);
LOG.info("Logging Response :{}", res.getContentType());
}
}
Interceptors
- They intercept after entering
DispatcherServlet but before they reach a controller
HandlerInterceptor implementations are interceptors
preHandle(req, res, handler): boolean
- If request should continue or not
- Executed before the target handler is called
postHandle(req, res, handler, modelAndView)
- Executed after the target handler but before the
DispatcherServlet renders the view
afterCompletion(req, res, handler, ex)
- Callback after completion of request processing and view rendering
- Use cases
- Logging request, response
- Not good for security layer
- References
public class LoggerInterceptor implements HandlerInterceptor {
boolean preHandle(...) {}
void postHandle(...) {}
void afterCompletion(...) {}
}
- Should need to register using a
@Configuration class
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggerInterceptor())
}
}
Error Handlers
@ExceptionHandler inside @Controller / @RestController
- Global Exception handling via
@ExceptionHandler in @ControllerAdvice / @RestControllerAdvice
- The
*ControllerAdvice classes apply to all Controllers
- References:
Request Context
- Use attributes in
HttpServletRequest
- You can populate it at the filter level
- This is passed from the Controller handler method arguments
@RequestScope bean
- You can change this as much as you want, because instances from other requests do not see it
- Make something similar to
RequestContextHolder or SecurityContextHolder
- This is not something recommended by Spring team
- References: