在区别过滤器和拦截器之前我们先来了解一下SpringMVC的执行流程
spring工作流程描述:
- 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;
- DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
- DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法)
- 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)
- Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
- 根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;
- ViewResolver 结合Model和View,来渲染视图
- 将渲染结果返回给客户端。
知道了SpringMVC执行的流程了下面来说Filter和Interceptor的区别
Filter
Filter是依赖于Servlet容器的,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest以及HttpServletResponse的一些参数,包括:过滤低俗文字、危险字符等。
Filter主要有以下几个用途:
- 在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest;
- 根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据;
- 在HttpServletResponse到达客户端之前,拦截HttpServletResponse;
- 根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。
关于如何修改参数,这篇博客讲的很好:在Filter中修改HttpServletRequest的参数
Interceptor
依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。
Filter和Interceptor的区别
- Filter依赖于Servlet容器,而Interceptor依赖于Web框架;
- Filter对几乎所有的请求起作用,而Interceptor只能对Controller的action请求起作用;
- 在Controller的生命周期里,Interceptor可以被多次调用,而Filter只能在容器初始化时调用一次。
Filter和Interceptor的执行顺序
只有一个Filter和Interceptor时
过滤前->拦截前->Controller的action执行->拦截后->过滤后
有多个Filter和Interceptor时
Filter和Interceptor之间的执行顺序不变,而多个Filter和多个Interceptor的执行顺序和它们的配置顺序是一致的。
//在web.xml文件中配置Filter
<!-- 自定义过滤器:testFilter1 -->
<filter>
<filter-name>testFilter1</filter-name>
<filter-class>com.ding.TestFilter1</filter-class>
</filter>
<filter-mapping>
<filter-name>testFilter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 自定义过滤器:testFilter2 -->
<filter>
<filter-name>testFilter2</filter-name>
<filter-class>com.ding.TestFilter2</filter-class>
</filter>
<filter-mapping>
<filter-name>testFilter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
//在spring-mvc.xml配置文件中配置Interceptor
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.ding.interceptor.TestInterceptor1" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.ding.interceptor.TestInterceptor2" />
</mvc:interceptor>
</mvc:interceptors>
根据它们的配置顺序,执行顺序为:
testFilter1->testFilter2->TestInterceptor1->TestInterceptor2->Controller中的action执行->TestInterceptor2->TestInterceptor1->testFilter2->testFilter1
Interceptor的应用——实现登录验证
当使用到springmvc做登录模块的时候,总会遇到需要判断用户是否合法登录,一般的做法就是用拦截器判断用户的session是否为空,通过拦截器获取到用户session里面的数据,判断是否未登录或者未合法登录,如果未登录就重定向到登录页面。
拦截器拦截登录的例子:
import com.ding.model.User;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 自定义的拦截器,实现HandlerInterceptor
*/
public class UserInterceptor implements HandlerInterceptor {
/**
*成功获得HandlerAdapter后,在Handler执行之前调用这个方法
*/
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
String path = httpServletRequest.getServletPath();
if ("/user/userLogin".equals(path)){//登陆接口
return true;
} else {//其他接口
//获取用户的session
User user = (User) httpServletRequest.getSession().getAttribute("user");
if (user == null){//未登录
//重定向
httpServletResponse.sendRedirect("/user/userLogin");
return false;
} else {//已登录
return true;
}
}
}
/**
* Handler执行完成之后调用这个方法
*/
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
/**
*Handler执行之后,ModelAndView返回之前调用这个方法
*/
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
参考文章:https://blog.csdn.net/xiaoyaotan_111/article/details/53817918