转载:https://www.zifangsky.cn/710.html
1. Filter(过滤器)和 Interceptor(拦截器)的区别
- 规范不同:
是Filter
规范规定的,依赖于Servlet
容器;Servlet
是Interceptor
规定的,依赖于Spring
框架。Spring
- 实现原理不同:
基于函数回调;Filter
基于java反射。Interceptor
- 使用范围不同:
依赖于Filter
容器,只能用于Servlet
程序;Web
既可用于Interceptor
程序,也可以用于Web
、Application
等程序中。Swing
- 使用的资源不同:
是Interceptor
的一个组件,归Spring
管理,配置在Spring
文件中,可以使用Spring
里的任何资源和对象,例如Spring
对象、数据源、事务管理等,通过Service
注入到IoC
既可;Interceptor
则不能。Filter
- 深度不同:
只在Filter
前后起作用,Servlet
能够深入到方法前后,异常抛出前后等。在Interceptor
中应该优先使用Spring
。Interceptor
2. 多个过滤器与多个拦截器的代码执行顺序
如果一个项目中同时有多个
Filter
,并且有多个
Interceptor
,那么它们的调用顺序是什么样的呢?
Filter1.java
package com.tao.springstarter.web.filter;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Filter1 extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 在DispatcherServlet之前执行
System.out.println("进入 Filter1 doFilterInternal()");
// 调用下一个filter
filterChain.doFilter(request, response);
// 在试图页面返回给客户端之前执行
System.out.println("退出 Filter1 doFilterInternal()");
}
}
Filter2.java
package com.tao.springstarter.web.filter;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Filter2 extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 在DispatcherServlet之前执行
System.out.println("进入 Filter2 doFilterInternal()");
// 调用下一个filter
filterChain.doFilter(request, response);
// 在试图页面返回给客户端之前执行
System.out.println("退出 Filter2 doFilterInternal()");
}
}
web.xml
中配置
Filter1
和
Filter2
<!-- 注册Filter -->
<filter>
<filter-name>Filter1</filter-name>
<filter-class>com.tao.springstarter.web.filter.Filter1</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>Filter2</filter-name>
<filter-class>com.tao.springstarter.web.filter.Filter2</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Interceptor1.java
package com.tao.springstarter.web.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Interceptor1 implements HandlerInterceptor {
/**
* 在DispatcherServlet之前执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("执行 Interceptor1 preHandle()");
return true;
}
/**
* 在Controller执行之后执行
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("执行 Interceptor1 postHandle()");
}
/**
* 在页面渲染完成返回给客户端之前执行
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("执行 Interceptor1 afterCompletion()");
}
}
Interceptor2.java
package com.tao.springstarter.web.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Interceptor2 implements HandlerInterceptor {
/**
* 在DispatcherServlet之前执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("执行 Interceptor2 preHandle()");
return true;
}
/**
* 在Controller执行之后执行
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("执行 Interceptor2 postHandle()");
}
/**
* 在页面渲染完成返回给客户端之前执行
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("执行 Interceptor2 afterCompletion()");
}
}
spring-servlet.xml
中配置
Interceptor1
和
Interceptor2
<mvc:interceptors>
<!-- 公共拦截器Interceptor1, 对所有请求都拦截 -->
<bean name="interceptor1" class="com.tao.springstarter.web.interceptor.Interceptor1"/>
<!-- 特定拦截器Interceptor2 -->
<mvc:interceptor>
<!-- 对/test进行拦截 -->
<mvc:mapping path="/test"/>
<!-- 特定请求的拦截器只能有一个 -->
<bean name="interceptor2" class="com.tao.springstarter.web.interceptor.Interceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
测试用的
TestController
:
package com.tao.springstarter.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String filterAndInterceptor1() {
System.out.println("调用 TestController#filterAndInterceptor1()");
return "filterAndInterceptor1";
}
@RequestMapping("/haha")
@ResponseBody
public String filterAndInterceptor2() {
System.out.println("调用 TestController#filterAndInterceptor2()");
return "filterAndInterceptor2";
}
}
请求
http://localhost:8080/ss/test
请求
http://localhost:8080/ss/haha
可以看到此时
Interceptor2
没有起作用。
其最终的执行流程就如下图所示: