Skip to content

拦截器

Spring Boot 中,拦截器(Interceptor)用于在请求到达 Controller 之前或响应返回客户端之前,对请求和响应进行预处理或后处理。

HandlerInterceptor

Spring MVC 提供了 HandlerInterceptor 接口,主要有三个方法:

java
public interface HandlerInterceptor {

    // 在 Controller 方法执行前调用
    default boolean preHandle(HttpServletRequest request,
                              HttpServletResponse response,
                              Object handler) throws Exception {
        return true;
    }

    // Controller 方法执行后,但视图渲染前调用
    default void postHandle(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler,
                            ModelAndView modelAndView) throws Exception {
    }

    // 请求处理完成后调用(即使出现异常也会调用)
    default void afterCompletion(HttpServletRequest request,
                                 HttpServletResponse response,
                                 Object handler,
                                 Exception ex) throws Exception {
    }
}
  • preHandle 返回 true 表示继续处理请求,返回 false 则会中断请求(常用于权限校验、日志、限流等)。

  • postHandle 用于修改返回的 ModelAndView,适合在渲染视图前处理数据。

  • afterCompletion 用于清理资源、记录日志或异常处理。

自定义拦截器

假设你要做一个简单的登录检查:

java
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Object user = request.getSession().getAttribute("user");
        if (user == null) {
            response.sendRedirect("/login");
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        // 可以在这里添加公共数据到 modelAndView
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 清理资源
    }
}

注册拦截器

Spring Boot 中可以通过实现 WebMvcConfigurer 来注册拦截器:

java
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 MyWebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**")      // 拦截所有请求
                .excludePathPatterns("/login", "/css/**", "/js/**"); // 排除登录页和静态资源
    }
}
  • addPathPatterns 用于指定拦截路径。

  • excludePathPatterns 用于排除路径,比如登录页或静态资源。

多个拦截器

多个拦截器按顺序执行

java
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 登录检查
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/login", "/css/**");

        // 日志拦截
        registry.addInterceptor(new LogInterceptor())
                .addPathPatterns("/**");

        // 权限拦截(例如接口权限)
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/api/**");
    }
}
  1. preHandle:Login → Log → Auth
  2. Controller 执行
  3. postHandle:Auth → Log → Login
  4. afterCompletion:Auth → Log → Login

如果 LoginInterceptor preHandle 返回 false,Log 和 Auth 的 preHandle 不会执行,但 Login 的 afterCompletion 仍然会被调用。