拦截器与过滤器的区别

在做Java Web项目时,经常会碰到拦截器与过滤器的配置,但一般都是从网上复制别人的代码,很少思考它们之间的区别。
现在有时间了,结合很久之前对Spring MVC研究来总结一下。

过滤器

目前的项目还是使用Spring MVC构建的,所以难免会配置一些Web.xml文件,关于Java Web的知识还是大学的时候学的,后面就去开发Android,也没怎么关注里面配置的含义。
Web.xml里面最常见的就是编码过滤器,它的配置如下:

<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <async-supported>true</async-supported>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

上面的async-supported标签的含义是异步处理,关于Servlet的异步处理我会在后面的文章中阐述,因为异步处理也是一个很重要的功能点,如果我们的接口有比较耗时的任务,可以考虑使用异步处理。

上面的配置很简单,主要目的是对Http的请求设置统一编码,至于它是如何实现的不在本文的讨论范围。下面我们来看看Filter接口中的方法,这是比较重要的。

public interface Filter {

    public void init(FilterConfig filterConfig) throws ServletException;

    public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException;

    public void destroy();

}

我们来看比较重要的doFilter方法,其实Servlet给我提供的Filter接口中给出的都是关于Http请求相关的对象,比如request、response,这就表明过滤器只能对Http请求相关的内容进行处理,这也说明Filter其实是Servlet特有的,普通项目中并不能使用过滤器的概念。

拦截器

拦截器是Spring中特有的概念,理论上Spring的项目都可以使用拦截器这个概念,不仅限于Web项目。
其实在Android项目中也有依赖注入的框架,记得Spring好像也有Android版本的,但是移动端的性能有限,不能像跑在服务器上面的Web应用那样使用各种反射,因为这些功能是很消耗资源的。

  1. 拦截器的抽象类
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {

    /**
     * This implementation always returns {@code true}.
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
        return true;
    }

    /**
     * This implementation is empty.
     */
    @Override
    public void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception {
    }

    /**
     * This implementation is empty.
     */
    @Override
    public void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    }

    /**
     * This implementation is empty.
     */
    @Override
    public void afterConcurrentHandlingStarted(
            HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
    }

}

跟拦截器生命周期相关的代码我们就不看了,因为这些方法并不常用,但是在Android里面生命周期却非常重要,主要是移动应用的状态比较多的缘故。
我们来看比较重要的preHandler方法,它与Filter不同的地方是多了一个handler的参数,其实它的实例是HandlerMethod对象,它持有我们URL对应的方法,
也就是Controller使用RequestMapping注解的方法,其实在这个地方就体现了Spring切面编程的思想,当然这些思想的实现都利用到了代理,否则我们怎么能拿到一个对象的方法呢。
有了这个handler我们就可以对方法中的参数进行预处理或者一些其它的操作,这是过滤器无法实现的功能,如果使用的是Spring构建的Web项目,完全可以用拦截器来替代过滤器。

发表评论

电子邮件地址不会被公开。 必填项已用*标注