文章目录
- 拦截器是什么?
- 怎么实现拦截器?
- 多个拦截器如果协同工作?
- 拦截器与过滤器
拦截器是什么?
拦截器顾名思义,就是一种用于拦截某样东西的一种技术,而他拦截的东西就是数据的请求,他的功能特点与Servlet的过滤器差不多,不过他们在各方面都有区别,这个后面再介绍。。
拦截器可以说是由Spring提供的一项拦截技术,并且在springmvc中也很好的运用了他
在SpringMVC的执行流程中,一个请求打到服务端,就会被DispacterServlet接收,随后DispacterServlet他就会以分发的形式找到HandlerMapping,在这里面就存储着所有的url信息,如果匹配不上对应的url,那就返回404。如果匹配上了,那么就会返回他符合条件的拦截器链
为什么说是“链”?
因为我们可以同时配置多个拦截器,一个请求也可以同时匹配上多个拦截器,他们的调用关系有点类似一种链装结构(跟过滤器链有点类型)
怎么实现拦截器?
主要分三步
- 通过实现HandlerInterceptor接口将一个类声明为拦截器类,通过重写其三个方法实现我们想要的拦截器功能
- 将一个WebMvcConfigurer对象注入到spring容器,通过重写addInterceptors()完成对拦截器对象的注入
- 在addInterceptors()中完成对拦截对象的筛选
具体实现
步骤一:完成拦截器类的声明
@Component
public class Interceptor1 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//第一个方法如果返回true就代表放行,如果返回false就代表拦截,程序就终止于此
if(XXX==null){
return true;
}
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
步骤二、三:完成拦截器对象的注册,以及指定拦截范围
//方式一:
@Configuration
public class Webconfig1 implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new Interceptor1())//注入拦截器对象
.addPathPatterns("/**")//指定拦截对象类型
.excludePathPatterns("/", "/log", "/images/**", "/checks");//指定放行对象类型
}
}
@Configuration
public class Webconfig2 {
@Bean
public WebMvcConfigurer configurer() {
return new WebMvcConfigurer() {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new Interceptor1()).
addPathPatterns("/**").
excludePathPatterns("/abc");
}
};
}
}
多个拦截器如果协同工作?
要了解多个拦截器的协同机制就得先了解单个拦截器的机制
- 实现拦截器需要重写HandlerInterceptor接口的三个方法
- preHandle():执行时机是进入handler之前,返回值类型为boolean,如果返回true代表放行,如果返回false代表拦截,就代表着这次请求就终止在这
- postHandle():执行时机是进入handler以后、视图渲染前。这里的返回值类型是void。代表着这里已经不起拦截作用了。在这我们可以获取处理以后的modelAndView,可以在视图渲染之前进行一些对数据的操作
- afterCompletion():执行时机是视图渲染后。在这里的可以获取到视图渲染后的一些异常信息。
- 单个拦截器的执行顺序:preHandle() -> postHandle() -> afterCompletion()
多个拦截器协同执行机制
了解完这再来看这张图或许清晰许多
这里就只列举了两个拦截器的协同机制,更多个的机制以此类推即可。。。
- 因为preHandle()是在执行handler之前就执行的,所以所有拦截器的preHandle()按注册顺序执行
- 执行完handler以后,就以逆序的形式执行postHandle()
- 执行完视图渲染后,也是按照逆序执行afterCompletion()
- 特殊情况:如果1号放行(pre()返回true),而2号拦截(pre()返回false)。这时候先得明确1号拦截器是正常工作的,而2号拦截器是停止工作的,那么2号后续的2个方法都不执行。由于1号的postHandle() 需要2号的postHandle() 调用,而2号的后续方法已经停止工作了,那么1号的postHandle()就不会执行,直接跳到1号的afterCompletion(),然后结束返回数据给客户端
拦截器与过滤器
拦截器与过滤器都起到了对数据的拦截功能,但是两者肯定是有区别的,不然为什么会将他们分开呢?是吧!
区别
- 归属对象不同
- 拦截器是SpringMVC执行流程中的一个组件,只有执行了SpringMVC那一套流程才会经过拦截器(约定已经配置且在拦截范围之内),而原生Servlet是与之不同的流程,那么就是说走原生Servlet无论如何都不会经过拦截器
- 过滤器是Web的三大组件之一(Servlet、Filter、Listener),那么就代表他是归Servlet管理,只要实现了Servlet接口的对象就会经过过滤器(约定在拦截范围之内),那么就是说原生Servlet与SpringMVC都有可能经过过滤器
- 执行时间不一样
- 过滤器是在进入tomcat之后、进入Servlet之前执行
- 拦截器是在进入Servlet之后,进入Controller之后执行