过滤器Filter

概念:Filter 过滤器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。
过滤器可以把对资源的请求拦截下来,从而实现一些特殊的处理。
过滤器一般完成一些通用的操作,比如:登陆鉴权、统一编码处理、敏感字符处理等。

步骤:
1.定义类,实现Filter接口,并重写其所有方法。
2.在类上定义@WebFilter注解,配置Filter拦截资源的路径。
3.在doFilter方法中执行逻辑,并放行。
4.在引导类上只用@ServletComponentScan开启Servlet组件支持。其实就是让WebFilter生效

放行后访问对应的资源,资源访问完成后,还会回到Filter中,并执行放行后的逻辑

拦截器interceptor

概念:是一种动态拦截方法调用的机制,类似于过滤器。在Spring中动态拦截控制器中方法的执行。
作用:在指定的控制器中方法调用前后执行预先设定的代码,完成功能的增强。

步骤:
1.定义拦截器,定义注解Component, 实现Handlerlnterceptor接口,并重写其所有方法。
2.注册拦截器

拦截器和过滤器同时存在-执行流程

请求—>web服务器【 过滤器(doFilter()放行前) —> DispatcherServlet —> preHandle —> controller中定义的方法— postHandle —> afterCompletion —> (doFilter()放行后) 】—>响应

【SpringBoot中实现过滤器和拦截器】

  1. 过滤器和拦截器简述
    过滤器Filter和拦截器Interceptor,在功能方面很类似,但在具体实现方面差距还是比较大的。
    都是Aop思想的一种体现,用来解决项目中某一类问题是两种接口(工具),都可以对请求做一些增强

  2. 过滤器的配置
    2.1 自定义过滤器,实现Filter接口(SpringBoot 3开始,jakarta.servlet.Filter)
    2.2 重写doFilter,实现过滤逻辑,酌情放行
    2.3 创建注解,实现过滤的范围配置

  3. 拦截器的配置
    3.1 自定义拦截器,实现HandlerInterceptor接口
    3.2 实现接口中的拦截方法(preHandle-请求执行前、postHandler-请求执行后、afterCompletion-视图渲染后)
    3.3 创建配置类,实现WebMvcConfigure

  4. 总结
    4.1 Filter依赖于Servlet容器,属于Servlet规范的一部分,而Interceptor依赖于SpringMVC框架:
    4.2 Filter的生命周期由Serylet容器管理,而Interceptor通过IOC容器来管理,可通过注入等方式来获取其Bean的实例
    4.3 Filter可拦截所有web资源(包括Jsp,Servlet,静态资源),而Interceptor则只拦截Controller。

案例:根据ip统计对controller的访问次数

使用过滤器实现—Servlet过滤器

1.创建filter包下MyFilter类并实现Filter接口一定要注意导入的包
2.重写doFilter,实现过滤逻辑后放行
3.在自定义的过滤器类上加@WebFilter(urlPatterns = "/*")注解,其中urlPatterns的值为过滤的路径
4.在APP启动类上加上@ServletComponentScan(basePackages = "com.xnj.filter")注解,其中basePackages的值为过滤器的包路径

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.xnj.filter;


import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;
import java.util.Objects;

/**
* 自定义过滤器,实现根据ip统计访问次数
*/
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("放行前的逻辑");
//获取HTTP请求对象
HttpServletRequest request = (HttpServletRequest) servletRequest;
//获取发送请求的客户端的IP地址。
String ip = request.getRemoteAddr();
//统计访问次数并输出
HttpSession session = request.getSession();
Integer count = (Integer) session.getAttribute("count");
count = Objects.isNull(count) ? 1 : ++count;
System.out.println("ip:"+ip+"\tcount:"+count);
session.setAttribute("count",count);
//放行
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("放行后的逻辑");
}

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

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

使用拦截器实现—SpringMVC拦截器

1.创建interceptor包下的MyInterceptor的自定义拦截器类并实现HandlerInterceptor接口
2.重写preHandle方法,请求执行前拦截,在方法内实现要执行的拦截逻辑,返回true就放行flase拦截
3.创建config包下Myconfig配置类,实现WebMvcConfigurer接口,并在类上添加@Configuration注解
4.配置类中重写addInterceptors方法来注册拦截器,在registry.addInterceptor()中添加自定义的拦截器对象

  • .addPathPatterns("/*")为拦截的请求路径
  • .excludePathPatterns()为排除的请求路径
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
27
28
package com.xnj.interceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Objects;

@Component
public class MyInterceptor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取发送请求的客户端的IP地址。访问的ip
String ip = request.getRemoteAddr();
//统计访问次数并输出
HttpSession session = request.getSession();
Integer count = (Integer) session.getAttribute("count");
count = Objects.isNull(count) ? 1 : ++count;
System.out.println("ip:"+ip+"\tcount:"+count);
session.setAttribute("count",count);
//放行
return true;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.xnj.config;

import com.xnj.interceptor.MyInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
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 MyConfig implements WebMvcConfigurer{
@Autowired
private MyInterceptor myInterceptor;

//注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加拦截器,拦截所有请求
registry.addInterceptor(myInterceptor).addPathPatterns("/**");
}
}

八股—拦截器和过滤器的区别

  1. 运行顺序不同
    过滤器是Servlet容器接收到请求之后,但是在Servlet容器调用之前运行的
    拦截器则在Servlet被调用之后,但是在响应被发送到客户端之前运行的。

  2. 配置方式不同
    过滤器是在web.xml里面去进行配置
    拦截器是在spring的配置文件中去进行配置,或者使用注解的方式进行配置

  3. Filter依赖于Servlet容器,而interceptor不依赖于Servlet容器

  4. Filter在过滤器中只能对request和response进行操作,而interceptor可以对request、response、handler、modelAndView、exception进行操作,相当于interceptor多了对于SpringMVC生态下的组件的一个操作能力