springmvc之过滤器与拦截器

一.前言

  • Filter是Spring框架中的一个过滤器,然而过滤器就是对其中请求的信息进行处理,然后再传送。Filter不像Servlet,它不能产生一个请求或者响应,它只能修改对某一资源的请求,或修改从某一的响应。它实现了javax.servlet.Filter接口的服务端程序,主要作用是过滤字符编码、做一些业务逻辑判断,主要用于对用户请求进行预处理

  • Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。

  • Filter是基于函数回调(doFilter()方法)的,而Interceptor则是基于Java反射的(AOP思想)。
    Filter依赖于Servlet容器,而Interceptor不依赖于Servlet容器。
    Filter对几乎所有的请求起作用,而Interceptor只能对action请求起作用。
    Interceptor可以访问Action的上下文,值栈里的对象,而Filter不能。
    在action的生命周期里,Interceptor可以被多次调用,而Filter只能在容器初始化时调用一次。

二.过滤器

1.相关接口

init: 用于完成Filter 的初始化
doFilter:实现过滤功能,该方法就是对每个请求及响应增加的额外处理。
过滤器Filter也具有生命周期:init()->doFilter()->destroy(),由部署文件中的filter元素驱动
destroy:用于Filter 销毁前,完成某些资源的回收

2.web.xml配置
<!-- 设置过滤器 !-->
    <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>com.sxkj.filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/user/*</url-pattern>
    </filter-mapping>
3.定义过滤器LoginFilter
public class LoginFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器初始化...");
        chain.doFilter(request, response);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器doFilter...");

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;    
    }

    @Override
    public void destroy() {
        System.out.println("过滤器销毁...");
    }
}

在方法doFilter中的chain.doFilter(request, response)最终是调用Servlet的doService()方法

三.拦截器

1.接口方法介绍
  • preHandle(): 这个方法在业务处理器处理请求之前被调用,可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值Boolean 类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法。
  • postHandle():这个方法在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。
  • afterCompletion():该方法也是需要当前对应的Interceptor 的preHandle 方法的返回值为true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。
2.执行流程
  • 1.程序先执行preHandle()方法,如果该方法的返回值为true,则程序会继续向下执行处理器中的方法,否则将不再向下执行。
  • 2.在业务处理器(即控制器Controller类)处理完请求后,会执行postHandle()方法,然后会通过DispatcherServlet向客户端返回响应。
  • 3.在DispatcherServlet处理完请求后,才会执行afterCompletion()方法。
3.拦截器配置

在springmvc.xml中加入配置如下:

 <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/user/**"/>
            <bean class="com.sxkj.interceptor.LoginIntercepter"/>
        </mvc:interceptor>
    </mvc:interceptors>

对静态资源文件的访问

<mvc:resources mapping="/images/**"  location="/images/"/> 
<mvc:resources mapping="/css/**"  location="/css/" />
4.定义LoginIntercepter
/**
 * 用户登录状态拦截器
 */
public class LoginIntercepter111 implements HandlerInterceptor {
    /**
     * 该方法将在Controller处理之前进行调用
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        return true;
    }

    /**
     * @Description  该方法将在Controller处理之后进行调用
     **/
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    }

    /**
     * @Description  处理完请求后带调用
     **/
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    }

}

四.总结

过滤器的运行是依赖于servlet容器的,跟springmvc等框架并没有关系。并且多个过滤器的执行顺序跟web.xml文件中定义的先后关系有关。

拦截器的执行顺序跟在SpringMVC的配置文件中定义的先后顺序有关。

如下是过滤器与拦截器合并执行的流程
springmvc之过滤器与拦截器
拦截器(Interceptor)是基于Java的反射机制,而过滤器(Filter)是基于函数回调。从灵活性上说拦截器功能更强大些,Filter能做的事情,都能做,而且可以在请求前,请求后执行,比较灵活。Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验(比较泛的,比如登录不登录之类),再细的话,建议用interceptor。