在Spring Web项目中,一般都是会用filter或者interceptor用来处理功能的Http请求或者响应结果信息,Filter与Interceptor既相似又有所区别,本文将进行对比分析两者的概念和用法。
两者实现的功能和目的是一样的,都是用来拦截和处理Http请求,在请求到达真实的业务逻辑处理阶段,比如用户登录的认证过程等。
Filter是在Java Web应用中的拦截器,一般服务于以下流程:
HttpRequest —-> Filter —-> Servlet —-> Controller/Action/… —-> Filter —-> HttpResponse
根据上面的流程可以看出,Filter的作用就是在用户请求到达Servlet之前,进行拦截。在拦截到用户的请求后,我们可以实现一些自定义的业务逻辑,也可以针对服务器的响应数据进行修改。
Interceptor在许多Java Web框架中都有应用,在这些框架中都实现拦截器Interceptor。例如Struts2中的Interceptor、Spring MVC中的HandlerInterceptor等。相比于Filter,这些框架中的Interceptor的产生作用的时间和位置不一样,下面描述了应用了Spring MVC中的HandlerInterceptor的web请求流程:
HttpRequest —-> DispactherServlet —-> HandlerInterceptor —->Controller—-> HandlerInterceptor —-> HttpResponse
从上述的定义可以发现,Filter的作用区间在请求到达Servlet之前,Interceptor在请Dispatcher接收到用户请求之后,先于具体的业务逻辑操作。
Filter面对的所有的请求,无差别;Interceptor是面对具体的Controller。Filter先于Interceptor发生,Filter可以通过返回False的逻辑判断来中断当前的请求逻辑。
Filter的声明主要是在Web应用中的web.xml之中,示例如下:
?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<filter>
<filter-name>loginFilterfilter-name>
<filter-class>filter.LoginFilterfilter-class>
<init-param>
<param-name>systemparam-name>
<param-value>businessparam-value>
init-param>
<filter-mapping>
<filter-name>loginFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
............
web-app>
Filter的声明和使用基本上可以安装普通的servlet来处理即可。
Interceptor作为Spring框架的组成部分,作为Spring中的一个Bean来声明和使用的,可以基于注解以及applicationContext的应用上下文中声明。
@Component
public MyInterceptor implements HandlerInterceptor {
.......
}
基于配置文件的声明和定义在Spring的配置文件中的片段:
..............
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user/**"/>
<bean class="org.interceptor.MyInterceptor"/>
mvc:interceptor>
mvc:interceptors>
在配置文件中声明之时,其中可以指定mapping的路径,用以指定interceptor处理的主要url路径地址信息。
在Java Web中的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();
}
在Filter最主要的是实现doFilter的方法,处理request请求和响应,FilterChain中记录了请求的Filter处理链条。
Spring中的HandlerInterceptor的处理方法定义如下:
public interface HandlerInterceptor {
//在业务处理之前
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
//在业务处理之后
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;
//在整个业务处理完成之后的回调函数,比如渲染界面之后的资源回收和释放
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;
}
在Interceptor中主要是beforeHandle和postHandle两个主要的方法来实现,afterCompletion主要是作为回调函数来处理的。
两者的主要应用场景相同,比如用户登录认证,请求记录历史,session的检查和处理等等共有的行为和操作检查信息。
不同之处在于,如果使用Spring框架,比如Spring Boot/Spring MVC之类的,则建议使用Interceptor。如果并未使用任何框架,只是简单的Web应用和Servlet,则可以使用Filter。
Filter是在Java Web发展早期使用比较多的过滤器,随着Spring的发展和兴起,则Interceptor随着Spring而逐渐更为大家所熟知和使用。
本质上两者并无不同之处,功能也是类似和相同的。