拦截器Interceptor

定义: SpringMVC内置拦截机制,允许在请求被目标方法处理的前后进行拦截,执行一些额外操作;比如:权限验证,日志记录,数据共享等。

实现步骤

1、自定义拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Component
public class MyHandlerInterceptor01 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler){
System.out.println("MyInterceptor01...preHandle...");
return true;
}

/**
* postHandle是controller方法执行之后

*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView){
System.out.println("MyInterceptor01...postHandle...");
}

/**
* preHandler返回true,afterCompletion方法才会执行
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception){
System.out.println("MyInterceptor01...afterCompletion...");
}
}

2、注册拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Configuration//专门为SpringMVC底层做一些配置
public class MySpringMVCConfig implements WebMvcConfigurer{
@Autowired
MyHandlerInterceptor01 myHandlerInterceptor01;
@Autowired
MyHandlerInterceptor02 myHandlerInterceptor02;
@Autowired
MyHandlerInterceptor03 myHandlerInterceptor03;
//添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(myHandlerInterceptor01)
.addPathPatterns("/**");//拦截所有请求;
registry.addInterceptor(myHandlerInterceptor02)
.addPathPatterns("/**");//拦截所有请求;
registry.addInterceptor(myHandlerInterceptor03)
.addPathPatterns("/**");//拦截所有请求;
}
}

多个拦截器执行顺序

顺序执行preHandle –>目标方法 –>倒序postHandle –>渲染 –>倒序afterCompletion

image-20241225205855287
  • 只有执行成功的preHandle会倒序执行afterCompletion
image-20241225210311965

​ 当preHandle2失败时

  • postHandleafterCompletion从哪里炸,倒序链路从哪里结束

  • postHandle失败不会影响afterCompletion

image-20241225211550522

​ 当postHandl2有异常时

过滤器Filter

定义: 过滤器在Java Servlet API中定义,允许你对HTTP请求和响应进行拦截、修改或处理。

实现步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//@WebFilter("/hello")  //原生的web注解就没用了
@Component //默认拦截所有请求
public class HelloFilter implements Filter {


@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filter 前置...");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("filter 后置...");
}

@Override
public void destroy() {
Filter.super.destroy();
}
}

  • init方法: 过滤器的初始化方法。在web服务器启动的时候会自动的创建Filter过滤器对象,在创建过滤器对象的时候会自动调用init初始化方法,这个方法只会被调用一次。

  • doFilter方法:这个方法是在每一次拦截到请求之后都会被调用,所以这个方法是会被调用多次的,每拦截到一次请求就会调用一次doFilter()方法。

  • destroy方法: 是销毁的方法。当我们关闭服务器的时候,它会自动的调用销毁方法destroy,而这个销毁方法也只会被调用一次。

执行顺序

image-20241225221531877

对于多个过滤器执行顺序:是按过滤器类名的自动排序确定的,类名排名越靠前,优先级越高。

两者区别

image-20241225224746780

1.出身不同

过滤器来自于 Servlet,而拦截器来自于 Spring 框架

image-20241225230546110 image-20241225230701686

2.触发时机不同

过滤器会先执行,然后才会执行拦截器,最后才会进入真正的要调用的方法

image-20241225230333224

3.实现方法不同

过滤器是基于方法回调实现的,我们在上面实现过滤器的时候就会发现,当我们要执行下一个过滤器或下一个流程时,需要调用 FilterChain 对象的 doFilter 方法进行回调执行

1
2
3
4
5
6
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filter 前置...");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("filter 后置...");
}

拦截器是基于动态代理(底层是反射)实现的

image-20241225231551074

4.支持的项目类型不同

过滤器是 Servlet 规范中定义的,所以过滤器要依赖 Servlet 容器,它只能用在 Web 项目中;

而拦截器是 Spring 中的一个组件,因此拦截器既可以用在 Web 项目中,同时还可以用在 Application 或 Swing 程序中。

5.使用的场景不同

因为拦截器更接近业务系统,所以拦截器主要用来实现项目中的业务判断的,比如:登录判断、权限判断、日志记录等业务。

过滤器通常是用来实现通用功能过滤的,比如:敏感词过滤、字符集编码设置、响应数据压缩等功能。