Spring MVC 拦截器
Spring MVC 拦截器(Interceptor)是 Spring 框架提供的一种用于在请求处理之前和之后对 HTTP 请求进行处理的机制。拦截器常用于处理日志、权限验证、性能监控等功能。
1. 定义拦截器
拦截器需要实现 HandlerInterceptor 接口,主要有三个方法:
preHandle(HttpServletRequest request, HttpServletResponse response, Object handler):在请求处理之前执行,返回true表示继续执行下一个拦截器或者目标方法,返回false则会停止后续拦截器链的执行。postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView):请求处理之后执行,但在视图渲染之前调用。afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex):请求处理完毕后执行,主要用于清理资源。
2. 创建拦截器
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
// 请求处理之前执行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle: 请求处理前");
// 返回true表示继续处理请求,返回false表示请求被拦截,后续处理不会执行
return true;
}
// 请求处理之后执行,但视图渲染之前
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle: 请求处理后,视图渲染前");
}
// 请求完全处理之后执行,主要用于资源清理
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion: 请求处理后,视图渲染后");
}
}
3. 注册拦截器
在 Spring MVC 配置中,你需要将拦截器注册到 HandlerInterceptor 接口中。通常有两种方式来进行配置:
3.1 使用 Java 配置(基于 WebMvcConfigurer)
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**") // 配置拦截路径,所有路径都会被拦截
.excludePathPatterns("/login", "/signup"); // 排除不需要拦截的路径
}
}
3.2 使用 XML 配置
如果你使用的是基于 XML 配置的 Spring MVC,你可以在 servlet-context.xml 文件中注册拦截器:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.example.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
4.多个拦截器指定顺序
4.1 通过 InterceptorRegistry 顺序控制
在 WebMvcConfigurer 中,拦截器的执行顺序是按照它们注册的顺序来的。注册的顺序决定了拦截器的执行顺序。第一个注册的拦截器会先执行,依此类推。
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 第一个拦截器
registry.addInterceptor(new FirstInterceptor())
.addPathPatterns("/**");
// 第二个拦截器
registry.addInterceptor(new SecondInterceptor())
.addPathPatterns("/**");
}
}
在这个例子中,FirstInterceptor 会先执行,然后是 SecondInterceptor
4.2 使用 @Order 注解显式指定顺序,配合 Spring Bean 自动装配
你也可以通过 @Order 注解显式指定每个拦截器的执行顺序。@Order 的值越小,拦截器的执行顺序越靠前。
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(1) // 顺序靠前
public class FirstInterceptor implements HandlerInterceptor {
// 实现方法
}
@Component
@Order(2) // 顺序靠后
public class SecondInterceptor implements HandlerInterceptor {
// 实现方法
}
@Component
@Order(3) // 最后执行
public class ThirdInterceptor implements HandlerInterceptor {
// 实现方法
}
在这个例子中,FirstInterceptor 会先执行,然后是 SecondInterceptor,因为 FirstInterceptor 的 @Order 注解值为 1,而 SecondInterceptor 的值为 2
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private FirstInterceptor firstInterceptor;
@Autowired
private SecondInterceptor secondInterceptor;
@Autowired
private ThirdInterceptor thirdInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(firstInterceptor).addPathPatterns("/**");
registry.addInterceptor(secondInterceptor).addPathPatterns("/**");
registry.addInterceptor(thirdInterceptor).addPathPatterns("/**");
}
}
5.执行顺序
当有多个拦截器时,并且各个方法都未发生异常,执行顺序为
- 先顺序执行各个拦截器的 preHandle 方法
- 然后执行 目标方法
- 然后倒序执行所有拦截器的 postHandle 方法
- 最后再倒序执行所有拦截器的 afterCompletion 方法
当 preHandle 发生异常时,postHandle 不会执行,但是 afterCompletion 会执行

浙公网安备 33010602011771号