一、概念
浏览器访问资源流程:
- 拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行
- 作用:
- 在指定的方法调用前后执行预先设定的代码
- 阻止原始方法的执行
- 拦截器与过滤器的区别
- 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
- 拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强
二、入门案例
声明拦截器的bean,并实现
HandlerInterceptor
接口(注意:扫描加载bean):@Component public class ProjectInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("ProjectInterceptor.preHandle()"); return true; }; @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("ProjectInterceptor.postHandle()"); }; @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("ProjectInterceptor.afterCompletion()"); }; };
定义配置类,继承
WebMvcConfigurationSupport
,实现addInterceptor方法并添加拦截器并设定拦截的访问路径,路径可以通过可变参数设置多个(注意:扫描加载配置):@Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport { @Autowired private ProjectInterceptor projectInterceptor; @Override protected void addInterceptors(InterceptorRegistry registry){ registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*"); }; };
SpringMvcConfig配置类与SpringMvcSupport配置类合并:
使SpringMvcConfig配置类实现WebMvcConfigurer接口,并在其中重写相关方法
(此方法有缺点:侵入性较强)
@Configuration @ComponentScan({"com.cikian.controller"};) @EnableWebMvc public class SpringMvcConfig implements WebMvcConfigurer { @Autowired private ProjectInterceptor projectInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*"); }; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/pages/**").addResourceLocations("/pages/"); registry.addResourceHandler("/css/**").addResourceLocations("/css/"); registry.addResourceHandler("/js/**").addResourceLocations("/js/"); registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/"); registry.addResourceHandler("/index.html").addResourceLocations("/index.html"); }; };
三、拦截器参数
1. 前置处理
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler)
throws Exception {
return true;
};
- 参数:
- request:请求对象
- response:响应对象
- handler:被调用的处理器对象,本质上是一个方法对象,对反射技术中的Method对象进行了再包装
- 返回值:
- 返回值为false,被拦截的处理器将不再执行
2. 后置处理
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView)
throws Exception {
};
- 参数:
- request:请求对象
- response:响应对象
- handler:被调用的处理器对象,本质上是一个方法对象,对反射技术中的Method对象进行了再包装
- modelAndView:如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行调整
3. 完成后处理
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex)
throws Exception {
};
- 参数:
- request:请求对象
- response:响应对象
- handler:被调用的处理器对象,本质上是一个方法对象,对反射技术中的Method对象进行了再包装
- ex:如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理
四、拦截器工作流程分析
五、多拦截器执行顺序
- 当配置多个拦截器时,形成拦截器链
- 拦截器链的运行顺序参照拦截器添加顺序为准
- 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
- 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作
拦截器链的运行顺序:
- preHandle:与配置顺序相同,必定运行
- postHandle:与配置顺序相反,可能不运行
- afterCompletion:与配置顺序相反,可能不运行