一直以来对这俩者的概念是混淆不清的,今天特写此文来理清概念。
过滤器
过滤器定义:
java Servlet规范中是这样定义的:过滤器(Filter)是java组件,允许运行过程中改变进入资源的请求和资源返回的响应中的有效负载和header信息。
Servlet 过滤器是
声明式的:过滤器通过 Web 部署描述符(web.xml)中的 XML 标签来声明。这样允许添加和删除过滤器,而无需改动任何应用程序代码或 JSP 页面。
动态的:过滤器在运行时由 Servlet 容器调用来拦截和处理请求和响应。
灵活的:过滤器在 Web 处理环境中的应用很广泛,涵盖诸如日志记录和安全等许多最公共的辅助任务。过滤器还是灵活的,因为它们可用于对来自客户机的直接调用执行预处理和后期处 理,以及处理在防火墙之后的 Web 组件之间调度的请求。最后,可以将过滤器链接起来以提供必需的功能。
模块化的:通过把应用程序处理逻辑封装到单个类文件中,过滤器从而定义了可容易地从请求/响应链中添加或删除的模块化单元。
可移植的:与 Java 平台的其他许多方面一样,Servlet 过滤器是跨平台和跨容器可移植的,从而进一步支持了 Servler 过滤器的模块化和可重用本质。
可重用的:归功于过滤器实现类的模块化设计,以及声明式的过滤器配置方式,过滤器可以容易地跨越不同的项目和应用程序使用。
透明的:在请求/响应链中包括过滤器,这种设计是为了补充(而不是以任何方式替代)servlet 或 JSP 页面提供的核心处理。因而,过滤器可以根据需要添加或删除,而不会破坏 servlet 或 JSP 页面。
所以 Servlet 过滤器是通过一个配置文件来灵活声明的模块化可重用组件。
写一个自定义Filter
创建Servlet和Filter
public class Servlet extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("这是测试Servlet");
}
}
public class FirstFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("second Filter init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println(request);
System.out.println(response);
System.out.println("第二个过滤器A");
chain.doFilter(request, response);
System.out.println("第二个过滤器B");
}
@Override
public void destroy() {
System.out.println("second Filter destory");
}
}
public class FirstFilter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("second Filter init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println(request);
System.out.println(response);
System.out.println("第二个过滤器A");
chain.doFilter(request, response);
System.out.println("第二个过滤器B");
}
@Override
public void destroy() {
System.out.println("second Filter destory");
}
}
配置文件
<filter>
<filter-name>FirstFilter</filter-name>
<filter-class>com.qiu.Filter.FirstFilter</filter-class>
<init-param>
<param-name>today</param-name>
<param-value>todays</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>SecondFilter</filter-name>
<filter-class>com.qiu.Filter.SecondFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SecondFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>testServlet</servlet-name>
<servlet-class>com.qiu.servlet.Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>testServlet</servlet-name>
<url-pattern>/Filter/*</url-pattern>
</servlet-mapping>
执行顺序
容器加载的时候,会执行过滤器的init()方法
执行doFilter()方法。通过调用FilterChain.doFilter()方法来处理请求,若没有,则请求中断。
随着服务器的关闭,调用destory()。
拦截器
拦截器定义
是springmvc提供的一个组件,前端控制器会先调用拦截器 ,然后再调用处理器。
依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理
拦截器方法
preHandle:前端控制器先调用拦截器的preHandle方法, 再调用处理器的处理方法。如果该方法的返回值为true,表示 继续向后调用。
postHandle:处理器的方法已经执行完毕,在将ModelAndView 返回给前端控制器之前执行该方法。所以,可以在该方法里面修改 ModelAndView。
- afterCompletion:最后执行的方法。
拦截器示例
- 自定义一个类实现HandlerInterceptor
public class interceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
//返回true,程序继续执行
//前端控制器先调用拦截器方法,在调用处理器方法
return true;
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
//处理器方法已经执行完毕,在这里可以修改ModelAndView,在返回给前端控制器
}
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
//Callback after completion of request processing
}
}
自定义业务逻辑方法
在spring配置文件中配置
<!-- 配置拦截器
可以在interceptors下面配置多个拦截器,
拦截器的执行的先后顺序由配置的先后顺序来决定。
注意:
如果要拦截多层路径,比如"/qiu/meng.do,
应该使用 /**。
-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="interceptors.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
过滤器和拦截器的比较
列表内容
- 拦截器是基于Java的反射机制的,而过滤器是基于函数回调。
- 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
- 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
- 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
- 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
- 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
从另一个角度说
- 使用范围不同 Filter 是Servlet 规定的.只能用于web 程序.而拦截器既可以用于Web 程序,也可以用于Apllicatioon,Swing程序中。
- 规范不同:Filter是在SerVlet 规范定义的,是Servlet容器支持的。而拦截器是在Spring 容器内的,Spring 框架所支持的。
- 使用资源不同:同其他代码块一样,拦截器也是一个Spring的组件,归Spring 管理。配置在Spring 中,因此能使用Spring 中的任何资源,对象,例如Service对象,数据源,事务管理等。通过Ioc注入到拦截器即可。而filter 则不能。
深度不同:Filter 只在Servlet前后起作用,而拦截器能深入到方法前后,异常抛出前后因而拦截器的使用具有更大的弹性,所以在spring 中优先使用拦截器。
过滤器: 依赖于servlet容器,使用回调函数,过滤范围大
拦截器: 依赖于框架容器 比如spring、mybatis ,灵活
本文参考了:http://blog.csdn.net/liveor_die/article/details/77435571#过滤器类
在加上自己的亲自试验而写。