一. SpringMVC中的拦截器(Interceptor)
下面是SpringMVC的流程图:(根据流程图我们看一下拦截器执行的位置)
1.作用:
拦截器是运行在DispatcherServlet
之后,在每个Controller
之前的,且运行结果可以选择放行或拦截!除此以外,拦截器还会运行在Controller
之后,关于拦截器,在处理某一个请求时,最多有3次执行!只不过,通常关注最多的是第1次执行,即在Controller
之前的那次(也就是上图中④的位置)!
2.基本使用:
需要自定义类,例如名为LoginInterceptor
,实现HandlerInterceptor
接口,重写3个抽象方法:
public class LoginInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("LoginInterceptor.preHandle()");
return false;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("LoginInterceptor.postHandle()");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("LoginInterceptor.afterCompletion()");
}
}
拦截器需要在Spring的配置文件中进行配置后才可以生效!所以,需要添加配置:
<!-- 配置拦截器链 -->
<mvc:interceptors>
<!-- 配置第1个拦截器 -->
<mvc:interceptor>
<!-- 指定拦截路径,不在拦截路径之内的将不予处理,即拦截器根本就不运行 -->
<mvc:mapping path="/user/info.do"/>
<mvc:mapping path="/user/password.do"/>
<!-- 指定拦截器类 -->
<bean class="cn.tedu.spring.interceptor.LoginInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
在拦截器类中,运行在Controller
之前的是preHandle()
方法,该方法返回true
表示放行,返回false
表示拦截!
例: 对于登录拦截器而言,可以判断Session中的用户数据,如果数据存在,视为已登录,可直接放行,如果没有数据,则视为没登录,需要重定向,并拦截:
public boolean preHandle(
HttpServletRequest request,
HttpServletResponse response, Object handler)
throws Exception {
System.out.println("LoginInterceptor.preHandle()");
// 判断Session中的数据,得知是否登录
HttpSession session = request.getSession();
if (session.getAttribute("username") == null) {
// Session中没有用户名,即:没有登录,则:重定向,并拦截
response.sendRedirect("../user/login.do");
// 返回false表示拦截
return false;
}
// 返回true表示放行
return true;
}
在配置拦截器时,根节点是<mvc:interceptors>
,用于配置拦截器链,即任何一个SpringMVC项目,都可以有若干个拦截器,从而形成拦截器链,如果某个请求符合多个拦截器的拦截配置,则会依次被各拦截器进行处理,任何一个拦截,都会导致后续不再将请求交给Controller
去处理!
在<mvc:interceptor>
中,<bean>
节点用于指定拦截器类;<mvc:mapping>
节点,用于配置拦截的请求路径,每个拦截器可以配置多个该节点,并且,在配置时,支持使用星号*
作为通配符,例如:<mvc:mapping path="/user/*"/>
,为了避免拦截范围过大,可以通过<mvc:exclude-mapping />
配置排除在外的请求路径,可以理解为白名单,该节点也可以配置多个:
<!-- 配置拦截器链 -->
<mvc:interceptors>
<!-- 配置第1个拦截器 -->
<mvc:interceptor>
<!-- 指定拦截路径,不在拦截路径之内的将不予处理,即拦截器根本就不运行 -->
<mvc:mapping path="/user/*" />
<!-- 指定白名单,列举的请求路径将不予处理,即拦截器根本就不运行 -->
<mvc:exclude-mapping path="/user/reg.do" />
<mvc:exclude-mapping path="/user/login.do" />
<mvc:exclude-mapping path="/user/handle_reg.do" />
<mvc:exclude-mapping path="/user/handle_login.do" />
<!-- 指定拦截器类 -->
<bean class="cn.tedu.spring.interceptor.LoginInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
注意:以上配置黑名单或白名单时,都可以使用星号*
作为通配符,但是,它只能匹配1层路径(或者说只能通配任意资源)!例如配置的是/user/*
,可以匹配/user/reg.do
或/user/login.do
,却无法匹配到/user/a/reg.do
或/user/a/b/login.do
这样的路径!如果需要匹配多层路径,可以使用2个星期,即**
,例如配置/user/**
则可以匹配以上任意路径!
3.拦截器与过滤器有什么区别:
1、拦截器是Interceptor,过滤器是Filter;
2、拦截器是SpringMVC中的组件,过滤器是Java EE中的组件;
3、拦截器是配置在Spring的配置文件中的,过滤器是配置在web.xml中的;
4、拦截器是运行在DispatcherServlet
之后、Controller
之前的,且在Controller
执行完后还会调用2个方法,而过滤器是运行在所有的Servlet
之前的;
5、拦截器的配置非常灵活,可以配置多项黑名单,也可以配置多项白名单,过滤器的配置非常单一,只能配置1项过滤路径;
拦截器与过滤器也有很多相似之处,例如:都可拒绝掉某些访问,也可以选择放行;都可以形成链。
相比之下,在一个使用SpringMVC框架的项目中,拦截器会比过滤器要好用一些,但是,由于执行时间节点的原因,它并不能完全取代过滤器!