docs
Handler interceptors for pre-processing and post-processing of requests, enabling cross-cutting concerns like logging, authentication, localization, and performance monitoring.
Interface for intercepting handler method execution with callbacks before, after, and upon completion of request processing.
/**
* Workflow interface that allows for customized handler execution chains.
* Applications can register any number of existing or custom interceptors
* for certain groups of handlers, to add common preprocessing behavior
* without needing to modify each handler implementation.
*/
public interface HandlerInterceptor {
/**
* Intercept the execution of a handler. Called after HandlerMapping determined
* an appropriate handler object, but before HandlerAdapter invokes the handler.
*
* @param request current HTTP request
* @param response current HTTP response
* @param handler chosen handler to execute, for type and/or instance evaluation
* @return true if the execution chain should proceed with the next interceptor
* or the handler itself. Else, DispatcherServlet assumes that this interceptor
* has already dealt with the response itself
* @throws Exception in case of errors
*/
default boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
return true;
}
/**
* Intercept the execution of a handler. Called after HandlerAdapter actually
* invoked the handler, but before the DispatcherServlet renders the view.
* Can expose additional model objects to the view via the given ModelAndView.
*
* @param request current HTTP request
* @param response current HTTP response
* @param handler the handler (or HandlerMethod) that started asynchronous execution
* @param modelAndView the ModelAndView that the handler returned
* @throws Exception in case of errors
*/
default void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* Callback after completion of request processing, that is, after rendering
* the view. Will be called on any outcome of handler execution, thus allows
* for proper resource cleanup.
*
* @param request current HTTP request
* @param response current HTTP response
* @param handler the handler (or HandlerMethod) that started asynchronous execution
* @param ex any exception thrown on handler execution, if any
* @throws Exception in case of errors
*/
default void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
}
}Usage Example:
public class LoggingInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
logger.info("Request URL: {} - Method: {} - Started at: {}",
request.getRequestURI(), request.getMethod(), startTime);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
logger.info("Request processed, view: {}",
modelAndView != null ? modelAndView.getViewName() : "null");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
long startTime = (Long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
logger.info("Request URL: {} - Completed in: {} ms",
request.getRequestURI(), duration);
if (ex != null) {
logger.error("Request failed with exception", ex);
}
}
}
// Authentication interceptor
public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
String authToken = request.getHeader("Authorization");
if (authToken == null || !authService.validateToken(authToken)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("Unauthorized");
return false;
}
User user = authService.getUserFromToken(authToken);
request.setAttribute("authenticatedUser", user);
return true;
}
}
// Configuration
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggingInterceptor())
.addPathPatterns("/**");
registry.addInterceptor(new AuthenticationInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api/public/**")
.order(1);
}
}Extension of HandlerInterceptor with a callback method for asynchronous request processing.
/**
* Extends HandlerInterceptor with a callback method invoked during asynchronous
* request handling.
*
* When a handler starts asynchronous request processing, the DispatcherServlet
* exits without invoking postHandle and afterCompletion, as it normally does,
* since the results of request handling (e.g. ModelAndView) are not available
* in the current thread and handling is not yet complete.
*/
public interface AsyncHandlerInterceptor extends HandlerInterceptor {
/**
* Called instead of postHandle and afterCompletion when the handler is being
* executed concurrently.
*
* Implementations of this method should use the provided request and response
* but avoid modifying them in ways that would conflict with the concurrent
* execution of the handler.
*
* @param request the current request
* @param response the current response
* @param handler the handler (or HandlerMethod) that started asynchronous execution
* @throws Exception in case of errors
*/
default void afterConcurrentHandlingStarted(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
}
}Contains and delegates calls to a HandlerInterceptor along with include and exclude path patterns.
/**
* Contains and delegates calls to a HandlerInterceptor along with include (and optionally
* exclude) path patterns to which the interceptor should apply.
*/
public final class MappedInterceptor implements HandlerInterceptor {
/**
* Create a new MappedInterceptor instance.
*
* @param includePatterns the path patterns to map with a null match to all paths
* @param interceptor the HandlerInterceptor to delegate to
*/
public MappedInterceptor(String[] includePatterns, HandlerInterceptor interceptor) {}
/**
* Create a new MappedInterceptor instance.
*
* @param includePatterns the path patterns to map
* @param excludePatterns the path patterns to exclude
* @param interceptor the HandlerInterceptor to delegate to
*/
public MappedInterceptor(String[] includePatterns, String[] excludePatterns,
HandlerInterceptor interceptor) {}
/**
* Return the path into the application for which this interceptor should apply.
* Supports direct matches, e.g. "/admin" and pattern matches, e.g. "/admin/**".
*
* @return the include patterns, or null
*/
public String[] getIncludePatterns() {}
/**
* Return the path patterns for which this interceptor should not apply.
*
* @return the exclude patterns, or null
*/
public String[] getExcludePatterns() {}
/**
* Return the actual interceptor.
*
* @return the interceptor
*/
public HandlerInterceptor getInterceptor() {}
/**
* Check whether this interceptor is mapped to the given request path.
*
* @param lookupPath the current request path
* @param pathMatcher the path matcher to use for pattern matching
* @return true if the interceptor applies to the given path
*/
public boolean matches(String lookupPath, PathMatcher pathMatcher) {}
}Usage Example:
@Bean
public MappedInterceptor adminInterceptor() {
return new MappedInterceptor(
new String[]{"/admin/**"},
new String[]{"/admin/login"},
new AdminAuthenticationInterceptor()
);
}Registry for configuring interceptors.
public class InterceptorRegistry {
public InterceptorRegistration addInterceptor(HandlerInterceptor interceptor) {}
}Configuration for a single interceptor.
public class InterceptorRegistration {
public InterceptorRegistration addPathPatterns(String... patterns) {}
public InterceptorRegistration excludePathPatterns(String... patterns) {}
public InterceptorRegistration pathMatcher(PathMatcher pathMatcher) {}
public InterceptorRegistration order(int order) {}
}