Cả hai chặn request trước khi tới controller, nhưng ở tầng khác nhau.
| Filter (Servlet) | HandlerInterceptor (Spring MVC) | |
|---|---|---|
| Tầng | Servlet container (trước DispatcherServlet) | Bên trong DispatcherServlet |
| Biết controller nào xử lý? | ❌ Chưa | ✅ Có (handler argument) |
| Truy cập Spring context | Hạn chế | ✅ Đầy đủ (là Spring bean) |
| Sửa request/response body | ✅ (wrap stream) | ❌ Khó |
| Use case điển hình | CORS, nén gzip, security (Spring Security là filter), logging thô | Auth theo handler, đo thời gian, set attribute cho view |
Filter:
java
@Component
class RequestLogFilter extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest req,
HttpServletResponse res, FilterChain chain) throws ... {
log.info("{} {}", req.getMethod(), req.getRequestURI());
chain.doFilter(req, res);
}
}HandlerInterceptor:
java
@Component
class TimingInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest req, HttpServletResponse res,
Object handler) {
req.setAttribute("start", System.currentTimeMillis());
return true; // false → chặn request, không tới controller
}
public void afterCompletion(HttpServletRequest req, HttpServletResponse res,
Object handler, Exception ex) {
long ms = System.currentTimeMillis() - (long) req.getAttribute("start");
log.info("Handled in {}ms", ms);
}
}
@Configuration
class WebConfig implements WebMvcConfigurer {
public void addInterceptors(InterceptorRegistry reg) {
reg.addInterceptor(new TimingInterceptor()).addPathPatterns("/api/**");
}
}Chọn cái nào: cần xử lý sớm/thô (security, CORS, nén) → Filter.
Cần biết controller/handler hoặc dùng Spring bean → Interceptor.
Both intercept requests before the controller, but at different layers.
| Filter (Servlet) | HandlerInterceptor (Spring MVC) | |
|---|---|---|
| Layer | Servlet container (before DispatcherServlet) | Inside DispatcherServlet |
| Knows which controller handles it? | ❌ Not yet | ✅ Yes (handler argument) |
| Access to Spring context | Limited | ✅ Full (it is a Spring bean) |
| Modify request/response body | ✅ (wrap streams) | ❌ Hard |
| Typical use cases | CORS, gzip, security (Spring Security is a filter), raw logging | Per-handler auth, timing, setting view attributes |
Filter:
java
@Component
class RequestLogFilter extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest req,
HttpServletResponse res, FilterChain chain) throws ... {
log.info("{} {}", req.getMethod(), req.getRequestURI());
chain.doFilter(req, res);
}
}HandlerInterceptor:
java
@Component
class TimingInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest req, HttpServletResponse res,
Object handler) {
req.setAttribute("start", System.currentTimeMillis());
return true; // false → blocks the request, controller not reached
}
public void afterCompletion(HttpServletRequest req, HttpServletResponse res,
Object handler, Exception ex) {
long ms = System.currentTimeMillis() - (long) req.getAttribute("start");
log.info("Handled in {}ms", ms);
}
}
@Configuration
class WebConfig implements WebMvcConfigurer {
public void addInterceptors(InterceptorRegistry reg) {
reg.addInterceptor(new TimingInterceptor()).addPathPatterns("/api/**");
}
}Which to use: for early/raw processing (security, CORS, compression) → Filter.
To know the controller/handler or use Spring beans → Interceptor.