Spring Web MVC的拦截器可以在进入controller前、controller后和请求完成后执行特定代码。

HandlerInterceptor


实现一个拦截器需要实现HandlerInterceptor接口。

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
@Component
public class AuthInterceptor implements HandlerInterceptor {
 
    private static final ThreadLocal<Long> info = new ThreadLocal<>();
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        
        // 模拟 Token 校验
        String token = request.getHeader("Authorization");
        if (token == null || token.isEmpty()) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write("Unauthorized access");
            return false; // 中断请求
        }
        
        info.set(token);
        return true; // 放行
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        // 后置处理
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
	    
        // 清理 ThreadLocal,防止线程池复用导致的内存泄漏
        info.remove();
    }
}

注册拦截器


实现WebMvcConfigurer接口并重写addInterceptors方法。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
@Configuration
public class WebConfig implements WebMvcConfigurer {
 
    @Autowired
    private AuthInterceptor authInterceptor;
 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor)
                .addPathPatterns("/api/**")              // 拦截的路径
                .excludePathPatterns("/api/login", "/api/register", "/static/**"); // 排除的路径
    }
}