Spring Boot 使用拦截器
拦截器与过滤器的区别
-
Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
-
Filter的执行由Servlet容器回调完成。
-
Filter的生命周期由Servlet容器管理,而拦截器则可以通过IOC容器来管理。
- 创建拦截器
public class Test1Interceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(">>>>>> Test1Interceptor preHandle");
// true : 不进行拦截, 继续执行 postHandle afterCompletion 方法
// false: 拦截, 不执行 postHandle afterCompletion 方法
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
- 加载拦截器
实现 WebMvcConfigurer 接口,并重写 addInterceptors 方法.使用 @Configuration 注解进行拦截器配置
/**: 表示拦截当前路径下的所有路径,包含子路径
/*: 表示只拦截当前路径下的所有路径
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// addPathPatterns 需要拦截的 url
// new TestInterceptor() 拦截器对象
registry.addInterceptor(new Test1Interceptor()).addPathPatterns("/test1/*");
}
}
配置多个拦截器
- 拦截器 1
public class Test1Interceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(">>>>>> Test1Interceptor preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
- 拦截器 2
public class Test2Interceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(">>>>>> Test2Interceptor preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
- 控制器 1
@RestController
@RequestMapping("/test1")
public class Test1Controller {
@GetMapping("/t")
public String test(){
return "/test1/t";
}
@GetMapping("/t/test")
public String test1(){
return "/test1/t/test";
}
}
- 控制器 2
@RestController
@RequestMapping("/test2")
public class Test2Controller {
@GetMapping("/t")
public String test(){
return "/test2/t";
}
}
- 拦截器配置
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 拦截 /test1/* 下的路径
registry.addInterceptor(new Test1Interceptor()).addPathPatterns("/test1/*");
// 拦截所有路径
registry.addInterceptor(new Test2Interceptor()).addPathPatterns("/**");
}
}
- 请求结果
示例 1 http://localhost:100/interceptor/test1/t
>>>>>> Test1Interceptor preHandle
>>>>>> Test2Interceptor preHandle
路径 /test1/t 与 /test1/* 和 /** 都能匹配成功, 故打印拦截器 1 和拦截器 2 的消息
示例 2 http://localhost:100/interceptor/test2/t
>>>>>> Test2Interceptor preHandle
路径 test2/t 与 /test1/* 不能匹配成功,但与 /** 匹配成功,故打印拦截器 2 的消息
结论
如果一个路径被多个拦截器匹配成功,则该路径会有多次拦截操作.
注意:
设置拦截路径时不要添加入 context-path 路径.
如访问地址是 http://localhost:100/interceptor/test2/t, 拦截路径不能使用 /interceptor/test2/t,这样是拦截会失效,替换为/test2/t可正常拦截.