文章目录
- [过滤器 与 拦截器](#过滤器 与 拦截器)
- 一、过滤器(Filter)
- [二、拦截器 Inteceptor](#二、拦截器 Inteceptor)
-
- 1、特点
- 2、生命周期
- 3、实现
- 4、拦截器链
-
- [1)配置 order](#1)配置 order)
- 2)执行顺序(没有异常)
- [3)某拦截器 preHandle 返回false](#3)某拦截器 preHandle 返回false)
- 4)执行顺序(有异常)
- 5)小结
- 三、执行顺序
-
- [1、自定义 Servlet](#1、自定义 Servlet)
- [2、自定义 Filter](#2、自定义 Filter)
- [3、自定义 Inteceptor](#3、自定义 Inteceptor)
- [4、对比:Servlet 与 Filter](#4、对比:Servlet 与 Filter)
- [5、对比:Filter 与 Inteceptor](#5、对比:Filter 与 Inteceptor)
- 6、小结
过滤器 与 拦截器
一、过滤器(Filter)
1、特点
过滤器是基于Java Servlet规范的一部分,用于在请求 到达Servlet之前 或 响应离开Servlet之后 对请求和响应进行处理。
- 过滤器可以对所有请求进行处理,不仅限于特定的Servlet或Spring MVC控制器。
- 过滤器在Servlet容器层面工作,而不是Spring层面。
- 适合用于日志记录、身份验证、权限检查等通用功能。
2、生命周期
java
public interface Filter {
// 初始化方法
default void init(FilterConfig filterConfig) throws ServletException {
}
// 执行拦截方法
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
// 销毁方法
default void destroy() {
}
}
markdown
# 创建【init方法】
1. 特点:
服务器启动,项目加载,创建filter对象,执行【init方法】(只执行一次)
2. 对比Servlet:
先于Servlet的init方法执行
# 拦截【doFilter方法】
1. 特点:
用户访问被拦截的目标资源时,执行【doFilter方法】(浏览器每访问一次,就会执行一次)
2. 对比Servlet:
先于Servlet的service方法执行
# 销毁【destroy方法】
1. 特点:
服务器关闭,项目关闭,销毁filter对象,执行【destroy方法】(只执行一次)
2. 对比Servlet:
后于Servlet的destroy方法执行
3、实现
定义拦截器只要实现Filter
接口,重写doFilter
方法即可
java
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 前置处理...
System.out.println("Filter doFilter before");
// 处理请求
chain.doFilter(request, response);
// 后置处理...
System.out.println("Filter doFilter after");
}
}
注册拦截器(SpringBoot示例)
java
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyFilter> myFilter() {
FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new MyFilter());
// 过滤路径(/*表示所有)
registrationBean.addUrlPatterns("/*");
// 过滤顺序(多个Filter按Order从小到大顺序执行)
registrationBean.setOrder(1);
return registrationBean;
}
}
4、过滤器链
1)配置 order
多个 Filter 按 Order的大小 从小到大 执行(如果没有配置Order,按 Bean声明的顺序 从上到下 执行)
java
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyFilter> myFilter1() {
FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new MyFilter1());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1);
return registrationBean;
}
@Bean
public FilterRegistrationBean<MyFilter> myFilter2() {
FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new MyFilter2());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(2);
return registrationBean;
}
@Bean
public FilterRegistrationBean<MyFilter> myFilter3() {
FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new MyFilter3());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(3);
return registrationBean;
}
}
2)执行顺序
java
Filter1 doFilter before
Filter2 doFilter before
Filter3 doFilter before
Servlet service
// 如果发生异常,就不会执行 doFilter after 了
Filter3 doFilter after
Filter2 doFilter after
Filter1 doFilter after
二、拦截器 Inteceptor
1、特点
拦截器是Spring MVC提供的功能,用于在请求到达控制器之前和响应离开控制器之后进行处理。
- 拦截器主要用于Spring MVC层面,处理的是控制器层的请求和响应。
- 适合用于权限检查、日志记录、请求计时等与业务逻辑密切相关的操作。
2、生命周期
java
public interface HandlerInterceptor {
// Controller执行之前调用
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
// Controller执行之后调用(发生异常 或 preHandle=false 不会调用)
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
// Controller执行之后调用(发生异常也会调用,preHandle=false不会调用)
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
3、实现
自定义拦截器只要实现HandlerInterceptor
接口,按需重写指定即可。
java
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Pre Handle method is Called");
return true; // 继续处理请求
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Post Handle method is Called");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("Request and Response is completed");
}
}
注册拦截器
java
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 MyInterceptor())
// 配置拦截路径
.addPathPatterns("/**")
// 配置放过路径
.excludePathPatterns();
}
}
4、拦截器链
1)配置 order
多个 Interceptor 按 Order的大小 从小到大 执行(如果没有配置Order,按 添加的顺序 从上到下 执行)
java
@Configuration
public class MyAdapter implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**").order(1);
registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**").order(2);
registry.addInterceptor(new MyInterceptor3()).addPathPatterns("/**").order(3);
}
}
2)执行顺序(没有异常)
java
Interceptor1 preHandle // true
Interceptor2 preHandle // true
Interceptor3 preHandle // true
Servlet service
Interceptor3 postHandle
Interceptor2 postHandle
Interceptor1 postHandle
Interceptor3 afterCompletion
Interceptor2 afterCompletion
Interceptor1 afterCompletion
3)某拦截器 preHandle 返回false
这里我们假设中间的 Interceptor2 的 preHandle 返回 false
java
Interceptor1 preHandle // true
Interceptor2 preHandle // false
Interceptor1 afterCompletion
properties
之前的拦截器(即 Interceptor1): 执行了 preHandle 和 afterCompletion
阻隔的拦截器(即 Interceptor2): 执行了 preHandle
之后的拦截器(即 Interceptor3): 全部不执行
4)执行顺序(有异常)
java
Interceptor1 preHandle // true
Interceptor2 preHandle // true
Interceptor3 preHandle // true
// 发生异常之前
Servlet service
// 这个竟然是在 异常的堆栈信息 之前执行的
Interceptor3 afterCompletion
Interceptor2 afterCompletion
Interceptor1 afterCompletion
异常的堆栈信息
// 发生异常之后,又整体执行了一遍....
Interceptor1 preHandle
Interceptor2 preHandle
Interceptor3 preHandle
Interceptor3 postHandle
Interceptor2 postHandle
Interceptor1 postHandle
Interceptor3 afterCompletion
Interceptor2 afterCompletion
Interceptor1 afterCompletion
5)小结
整体顺序:所有 preHandle -> Controller -> 所有 postHandle -> 所有 afterCompletion
markdown
# preHandle
1. 调用前提
无
2. 调用时机
Controller方法处理之前
3. 调用链顺序
顺序执行:preHandle1 ==> preHandle2 ==> preHandle3
# postHandle
1. 调用前提
preHandle返回true 且 Controller没有发生异常
2. 调用时机
Controller方法处理完之后,afterCompletion调用之前
3. 调用链顺序
倒序执行:postHandle3 ==> postHandle2 ==> postHandle1
# afterCompletion
1. 调用前提
preHandle返回true(Controller发生异常也会调用)
2. 调用时机
Controller方法处理完之后
3. 调用链顺序
倒序执行:afterCompletion3 ==> afterCompletion2 ==> afterCompletion1
三、执行顺序
1、自定义 Servlet
java
public class MyServlet extends HttpServlet {
@Override
public void destroy() {
System.out.println("Servlet destroy");
super.destroy();
}
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("Servlet init");
super.init(config);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet service");
resp.getWriter().write("Hello from MyServlet");
}
}
java
@Configuration
public class ServletConfig {
@Bean
public ServletRegistrationBean<MyServlet> myServlet() {
return new ServletRegistrationBean<>(new MyServlet(), "/myServlet");
}
}
2、自定义 Filter
java
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter init");
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 前置处理...
System.out.println("Filter doFilter before");
// 处理请求
chain.doFilter(request, response);
// 后置处理...
System.out.println("Filter doFilter after");
}
@Override
public void destroy() {
System.out.println("Filter destroy");
Filter.super.destroy();
}
}
java
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyFilter> myFilter() {
FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new MyFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1);
return registrationBean;
}
}
3、自定义 Inteceptor
java
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Interceptor preHandle");
return true; // 继续处理请求
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Interceptor postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("Interceptor afterCompletion");
}
}
java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns();
}
}
4、对比:Servlet 与 Filter
java
// 项目启动
Filter init
// 访问 http://localhost:8080/myServlet
Servlet init
Filter doFilter before
Servlet service
Filter doFilter after
// 项目关闭
Servlet destroy
Filter destroy
5、对比:Filter 与 Inteceptor
java
@RestController
public class TestController {
@GetMapping("/interceptor")
public ResponseEntity<String> interceptor() {
System.out.println("Servlet service");
return ResponseEntity.ok("SUCCESS");
}
}
java
// 项目启动
Filter init
// 访问 http://localhost:8080/interceptor
Filter doFilter before
Interceptor preHandle
Servlet service
Interceptor postHandle
Interceptor afterCompletion
Filter doFilter after
// 项目关闭
Filter destroy
6、小结
java
// 项目启动
Filter init
// 访问接口
Servlet init
Filter doFilter before
Interceptor preHandle
Servlet service
Interceptor postHandle
Interceptor afterCompletion
Filter doFilter after
// 项目关闭
Servlet destroy
Filter destroy