一、使用步骤
1.定义拦截器实现 Handlerlnterceptor接口;重写3个具体的拦截器方法。
public class MyInterceptor1 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("【" + this.getClass().getSimpleName() +"】处理器前方法");
// 返回true,不会拦截后续的处理
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("【" + this.getClass().getSimpleName() +"】处理器后方法");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("【" + this.getClass().getSimpleName() +"】处理器完成方法");
}
}
2.注册拦截器
@Configuration
public class WebAppConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器到Spring MVC机制,然后它会返回一个拦截器注册
InterceptorRegistration ir = registry.addInterceptor(new MyInterceptor1());
// 指定拦截匹配模式,限制拦截器拦截请求
ir.addPathPatterns("/test/*");
}
}
测试
测试Controller,这里没有配置页面,就简单测试了一下请求json数据的。
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping(value = "/json",method = RequestMethod.GET)
public String test(){
System.out.println("执行处理器逻辑");
return "success";
}
}
访问路径:http://localhost:8080/test/json
打印结果:
【MyInterceptor1】处理器前方法
执行处理器逻辑
【MyInterceptor1】处理器后方法
【MyInterceptor1】处理器完成方法
二、流程分析
- 执行preHandle方法
- 放行–执行处理器逻辑
- 执行postHandle方法
- 视图解析渲染
- 执行afterCompletion方法
三、多拦截器执行顺序
原则:处理器前方法采用先注册先执行,处理器后方法和完成
方法则是先注册后执行的规则
测试
配置第2个和第3个拦截器
MyInterceptor2
public class MyInterceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("【" + this.getClass().getSimpleName() +"】处理器前方法");
// 返回true,不会拦截后续的处理
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("【" + this.getClass().getSimpleName() +"】处理器后方法");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("【" + this.getClass().getSimpleName() +"】处理器完成方法");
}
}
MyInterceptor3
public class MyInterceptor3 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("【" + this.getClass().getSimpleName() +"】处理器前方法");
// 返回true,不会拦截后续的处理
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("【" + this.getClass().getSimpleName() +"】处理器后方法");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("【" + this.getClass().getSimpleName() +"】处理器完成方法");
}
}
注册拦截器2、3:
@Configuration
public class WebAppConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器到Spring MVC机制,然后它会返回一个拦截器注册
InterceptorRegistration ir = registry.addInterceptor(new MyInterceptor1());
// 指定拦截匹配模式,限制拦截器拦截请求
ir.addPathPatterns("/test/*");
//注册拦截器2
InterceptorRegistration ir2 = registry.addInterceptor(new MyInterceptor2());
ir2.addPathPatterns("/test/*");
//注册拦截器3
InterceptorRegistration ir3 = registry.addInterceptor(new MyInterceptor3());
ir3.addPathPatterns("/test/*");
}
}
执行结果
【MyInterceptor1】处理器前方法
【MyInterceptor2】处理器前方法
【MyInterceptor3】处理器前方法
执行处理器逻辑
【MyInterceptor3】处理器后方法
【MyInterceptor2】处理器后方法
【MyInterceptor1】处理器后方法
【MyInterceptor3】处理器完成方法
【MyInterceptor2】处理器完成方法
【MyInterceptor1】处理器完成方法
注意:拦截规则是一样的,同一个请求url会被这三个拦截器都拦截。
补充:拦截不通过的情况
这里假设第二个拦截器,没有放行。将MyInterceptor2 的preHandle方法返回值改为true,模拟不通过的情况。
修改MyInterceptor2 代码:
public class MyInterceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("【" + this.getClass().getSimpleName() +"】处理器前方法");
// 返回false,拦截请求
return fasle;
}
...
}
测试结果
【MyInterceptor1】处理器前方法
【MyInterceptor2】处理器前方法
【MyInterceptor1】处理器完成方法
分析:处理器前( preHandle )方法会执行,但是一旦返回 false ,则后续的拦截器、 处理器和所有拦截器的处理器后( postHandle ) 方法都不会被执行。完成方法 afterCompletion则不一样,它只会执行返回 true 的拦截器的完成方法,而且顺序是先注册后执行 。