spring-filter-intercepter-过滤器与拦截器
1. 过滤器 Filter
1.1 Filter 定义
Filter是sun公司中servlet2.3后增加的一个新功能,在javaEE中定义了一个接口 javax.servlet.Filter来描述过滤器。
Filter可以认为是Servlet的一种“加强版”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链。Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序.它依赖于servlet容器,在实现上,基于函数回调,它可以对几乎所有请求进行过滤。
1.2 Filter 工作原理
Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,其工作原理是,只要你在web.xml文件配置好要拦截的客户端请求,它都会帮你拦截到请求,此时你就可以对请求或响应(Request、Response)统一处理等。
使用Filter完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
- 当服务器启动,会创建Filter对象,并调用init方法,只调用一次。
- 当访问资源,路径与Filter的拦截路径匹配,会执行Filter中的doFilter方法,
- 当服务器关闭时,会调用Filter的destroy方法来进行销毁操作。
1.3 Filter 应用场景
在过滤器中修改字符编码(CharacterEncodingFilter)、在过滤器中修改HttpServletRequest的一些参数(XSSFilter(自定义过滤器)),如:过滤低俗文字、危险字符、敏感词过滤、响应信息压缩、控制权限、控制转向、做一些业务逻辑判断等。
1.4 Filter 实例
1.定义 Filter
package com.demo.filter;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;
/**
* @author gx
*/
@Component
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
System.out.println("这是 myFilter 过滤器!");
filterChain.doFilter(request, response);
System.out.println("这是 myFilter 过滤器执行后!");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("这是 myFilter 初始化");
}
@Override
public void destroy() {
System.out.println("这是 myFilter 销毁");
}
}
2. 配置过滤器
- 方式一:web.xml
<filter>
<description>测试过滤器</description>
<filter-name>TestFilter</filter-name>
<filter-class>com.test.filtes.TestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 方式二:通过@WebFilter注解配置
@WebFilter(urlPatterns = "/*")
@Component
public class MyFilter2 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
System.out.println("这是 myFilter2 过滤器!");
filterChain.doFilter(request, response);
System.out.println("这是 myFilter2 过滤器执行后!");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("这是 myFilter2 初始化");
}
@Override
public void destroy() {
System.out.println("这是 myFilter2 销毁");
}
}
启动类上可能需要这个注解:@ServletComponentScan
- 方式三:通过@Bean来配置
package com.demo.component;
import com.demo.filter.MyFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author gx
*/
@Configuration
public class MyConfig {
@Autowired
private MyFilter myFilter;
//可以设置 order
@Bean
public FilterRegistrationBean registrationBean(){
FilterRegistrationBean filterRegister = new FilterRegistrationBean(myFilter);
filterRegister.addUrlPatterns("/*");
//可以设置过滤器顺序
filterRegister.setOrder(0);
return filterRegister;
}
}
2. 拦截器 Interceptor
2.1 Interceptor 定义
拦截器(Interceptor)和Servlet无关,它依赖于Web框架,在SpringMVC中就依赖于SpringMVC框架,由SpringMVC框架实现。在Struts2中同理,它是一种可以让你在Action执行之前和Result执行之后进行一些功能处理的机制。
在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用。可以用于在某个方法或者字段被访问之前,进行拦截,然后在之前或者之后加入某些统一的处理方法。就是在action的前、后、甚至抛出异常时进行处理,比如动态代理就是拦截器的简单实现。
拦截器将很多service或者Controller中共有的行为提炼出来,在某些方法执行的前后执行,提炼为通用的处理方式,让被拦截的方法都能享受这一共有的功能,让代码更加简洁,同时,当共有的功能需要发生调整、变动的时候,不必修改很多的类或者方法,只要修改这个拦截器就可以了,可复用性很强。
SpringMVC的拦截器基于HandlerInterceptor接口来实现,所以只要实现HandlerInterceptor接口或者继承它的实现类。
2.2 Interceptor 工作原理
-
preHandler(HttpServletRequest request, HttpServletResponse response, Object handler) 方法在请求处理之前被调用。如果已经是最后一个 Interceptor 的时候就会调用当前请求的 Controller 方法。
-
postHandler(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 方法在当前请求处理完成之后,所以我们可以在这个方法中对 Controller 处理之后的 ModelAndView 对象进行操作。
-
afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法需要在当前对应的 Interceptor 类的 preHandle 方法返回值为 true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在 DispatcherServlet 渲染了对应的视图之后执行。此方法主要用来进行资源清理
2.3 Interceptor 应用场景
-
日志记录:记录请求操作日志(用户ip,访问时间等)
-
权限检查:判断用户是否有权限访问资源,如校验token 日志记录
-
性能监控:记录请求->响应时间,preHandle:记录开始时间,afterCompletion:记录结束时间,开始时间相减去结束时间
-
登录验证:判断用户是否登录
-
sign校验,封禁校验等
-
处理cookie,主题,国际化,本地化等
-
filter可以实现的功能intercepter基本上都能实现
2.4 Interceptor 实例
1. 定义拦截器
package com.demo.intercepter;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyIntercepter implements HandlerInterceptor {
//进入 handler 之前:权限认证等
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("myIntercepter:preHandel 方法!");
return true;
}
//进入 handler 之后,返回 modelAndView 之前
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("myIntercepter:postHandle 方法!");
}
//执行完 handler 之后
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("myIntercepter:afterCompletion 方法!");
}
}
Object handler 这个 handler 指拦截器拦截的内容,比如方法(HanderMethod)

2. 配置拦截器
- 方式一:web.xml
<mvc:interceptors>
<!-- 如果直接配置bean,代表对所有请求都拦截 -->
<bean name="myIntercepter" class="com.demo.intercepter.MyIntercepter" />
<mvc:interceptor>
<!-- /**:拦截所有,/*拦截一层目录结构请求 -->
<mvc:mapping path="/**"/>
<!-- 不拦截的请求 -->
<mvc:exclude-mapping path="/testRequestEntity"/>
<!-- 自定义的拦截器引用 -->
<ref bean="myIntercepter"></ref>
</mvc:interceptor>
<mvc:interceptors/>
- 方式二:WebConfig将拦截器注册添加到拦截器链
package com.demo.component;
import com.demo.intercepter.MyIntercepter;
import com.demo.intercepter.MyIntercepter1;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyIntercepter())
.addPathPatterns("/**")
.order(1);
}
}
spring 环境下这么玩
3. Filter 和 Interceptor 执行顺序

4. Filter 和 Interceptor 区别
过滤器(Filter)和拦截器(Interceptor)区别 | |||
过滤器(Filter) | 拦截器(Interceptor) | 总结 | |
定义位置 | Filter定义在java.servlet包下 | 接口HandlerInterceptor定义在org.springframework.web.servlet包下 | |
配置位置 | 配置在web.xml中 | 配置在springmvc.xml中 | |
作用位置 | Filter在只在 Servlet 前后起作用,Filter 通常不考虑servlet 的实现 | 拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用具有更大的弹性。允许用户介入(hook into)请求的生命周期 | 在Spring构架的程序中,要优先使用拦截器。几乎所有 Filter 能够做的事情, interceptor 都能够轻松的实现 |
使用范围 | Filter 是 Servlet 规范规定的 | 而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。 | |
遵循规范 | Filter 是遵循 Servlet 规范 | 而拦截器是在 Spring容器内的,是Spring框架支持的。 | |
与spring关系 | Filter 不能够使用 Spring 容器资源 | Interceptor 是被 Spring 调用 | Spring 中使用 interceptor 更容易 |
调用方 | Filter 是被 Server(like Tomcat) 调用 | Interceptor 是被 Spring 调用 | 因此 Filter 总是优先于 Interceptor 执行 |
实现方式 | Filter 基于函数回掉 | Interceptor基于java反射 | |
demo 示例
https://gitee.com/zangsan/apz/tree/master/demo-boot/demo-filter/src/main/java/com/demo

浙公网安备 33010602011771号