Spring拦截器可以拦截用户的请求并进行相应的处理,比如通过他来实现权限验证,或者用来判断用户是否登陆,或者是像12306那样判断当前时间是否是买票时间。
拦截器的实现方式
- 通过实现HandlerInterceptor或者继承HandlerInterceptor的实现类,如HandlerInterceptorAdapter。
- 通过实现WebRequestInterceptor接口或者继承WebRequestInterceptor的实现类
HandlerInterceptor实现
实现HandlerInterceptor接口
HandlerInterceptor一共有三个方法
- preHandle():此方法在业务处理器之前被调用,在该方法中对用户的request进行处理,如果你决定该拦截器对请求进行拦截之后还有必要去调用其他拦截器或者还需要调用业务代码,那就返回true,否则返回false。
- postHandle():此方法只有在preHandle方法返回true的时候才会被调用,发生在业务处理器处理完请求之后,在DispatcherServlet向客户端返回响应前被调用,在该方法中可以对用户返回的model进行修改。
- afterCompletion():此方法也是只有在perHandle方法返回true的时候才会被调用,发生在DispatcherServlet完成请求之后,在该方法中可以进行一些资源清理的操作。
拦截器的执行顺序
多个拦截器的执行顺序
当拦截器返回为false的执行顺序
配置拦截器
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/test"/>
<bean class="com.inspur.ssm.interceptor.TestInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/test"/>
<bean class="com.inspur.ssm.interceptor.TestInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
为什么postHandle执行的时候是倒叙?
org.springframework.web.servlet.HandlerExecutionChain.java文件源码
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
}
return true;
}
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = interceptors.length - 1; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
很明确的可以看到,一个是采用了正序,一个采用了是倒叙
拦截器和过滤器的区别
- 拦截器是基于java的反射机制的,而过滤器是基于函数回调的。
- 拦截器不依赖于Servlet容器,而过滤器依赖与Servlet容器。
- 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求其作用。
- 拦截器可以访问action的上下文、值栈里面的对象,而过滤器不能访问。
- 在action的声明周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次、(这里的调用一次,是对于构造函数而言的,而doFilter会对匹配的请求做持续的处理。)
- 拦截器可以获取IOC容器中的Bean,而过滤器不行。