Master Spring Boot Interceptors: From Basics to Advanced Techniques
This article explains what Spring MVC interceptors are, when to use them, provides a simple implementation and registration example, and then dives into advanced patterns such as MappedInterceptor, global interceptors, and asynchronous interceptors with complete code snippets and usage guidance.
1. Introduction
What is an interceptor? An interceptor is part of Spring MVC that works inside the Spring framework and allows you to modify requests and responses for specific controllers.
When should you use an interceptor? Use it for Spring‑specific logic such as:
Authentication and authorization: verify user credentials and permissions.
Recording execution time: measure and track how long a controller takes to handle a request.
Modifying model/view: adjust the model or view before sending the response.
Adding common attributes: include shared data (e.g., user details) in all responses.
Simple interceptor implementation
<code>public class DemoInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.err.println("preHandle...");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.err.println("postHandle...");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.err.println("afterCompletion...");
}
}</code>Register the interceptor:
<code>@Component
public class DemoConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new DemoInterceptor())
.addPathPatterns("/api/*");
}
}</code>When a request matches /api/* , the callbacks are executed, producing output such as:
<code>preHandle...
api query...
postHandle...
afterCompletion...</code>2. Advanced Cases
2.1 MappedInterceptor
Spring provides MappedInterceptor as a wrapper that matches URL patterns and automatically picks beans from the container.
<code>public class AuthInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(AuthInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("权限验证...");
return true;
}
}</code> <code>@Bean
MappedInterceptor authInterceptor(@Value("${pack.auth.patterns}") String[] includePatterns) {
return new MappedInterceptor(includePatterns, new AuthInterceptor());
}</code>2.2 Global Interceptor
By extending RequestMappingHandlerMapping you can add interceptors to all requests.
<code>@Component
public class PackHandlerMapping extends RequestMappingHandlerMapping {
private final List<HandlerInterceptor> interceptors;
public PackHandlerMapping(List<HandlerInterceptor> interceptors) {
this.interceptors = interceptors;
}
@Override
protected void extendInterceptors(List<Object> interceptors) {
List<HandlerInterceptor> ret = this.interceptors.stream()
.filter(i -> !(i instanceof MappedInterceptor))
.collect(Collectors.toList());
interceptors.addAll(ret);
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}</code>2.3 Asynchronous Interceptor
Spring MVC provides AsyncHandlerInterceptor with an extra method afterConcurrentHandlingStarted for async request processing.
<code>@Component
public class AsyncLogInterceptor implements AsyncWebRequestInterceptor {
public void preHandle(WebRequest request) {
System.err.printf("AsyncWebRequestInterceptor >>> %s, %s, 开始处理%n", System.currentTimeMillis(), Thread.currentThread().getName());
}
public void postHandle(WebRequest request, ModelMap model) {
System.err.printf("AsyncWebRequestInterceptor >>> %s, postHandle%n", Thread.currentThread().getName());
}
public void afterCompletion(WebRequest request, Exception ex) {
System.err.printf("AsyncWebRequestInterceptor >>> %s afterCompletion%n", Thread.currentThread().getName());
}
public void afterConcurrentHandlingStarted(WebRequest request) {
System.err.printf("AsyncWebRequestInterceptor >>> %s, %s, 异步处理%n", System.currentTimeMillis(), Thread.currentThread().getName());
}
}</code> <code>@Component
public class WebInterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addWebRequestInterceptor(new AsyncLogInterceptor())
.addPathPatterns("/admin/**");
}
}</code>Define a controller to test async handling:
<code>@GetMapping("/async")
public Callable<String> async() {
return new Callable<String>() {
public String call() throws Exception {
System.err.printf("%s, %s - 执行任务%n", System.currentTimeMillis(), Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(3);
return "异步数据";
}
};
}</code>Result is shown in the following image:
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.